/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = sybase_token.c                                                */
/*  NOTE      = TDS协议解析                                                   */
/*  DATE      = 2014/05/27 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <netinet/in.h>

#include "sybase_core.h"
#include "sybase_token.h"
#include "sybase_common.h"

#define FRTDS_NETBUF                4
#define FRTDS_RPLEN                 255
#define FRTDS_VERSIZE               4
#define FRTDS_PROGNLEN              10
#define FRTDS_OLDSECURE             2
#define FRTDS_HA                    6
#define FRTDS_SECURE                2
#define FRTDS_PKTLEN                6
#define FRTDS_CAP_REQUEST           1
#define FRTDS_CAP_RESPONSE          2
#define FRTDS_DATA_COLUMNSTATUS     58
#define FRTDS_DATA_NOCOLUMNSTATUS   38

#define FRTDS_DYN_PREPARE           0x01
#define FRTDS_DYN_EXEC_IMMED        0x08

#define FRTDS_DONE_COUNT            0x0010
#define FRTDS_CUR_ISTAT_ROWCNT      0x00000020
#define FRTDS_DONE_ERROR            0x0002
#define FRTDS_DONE_COUNT            0x0010
#define FRTDS_OFF_SELECT            0x016D
#define FRTDS_OFF_FROM              0x014F
#define FRTDS_OFF_ORDER             0x0165
#define FRTDS_OFF_COMPUTE           0x0139
#define FRTDS_OFF_TABLE             0x0173
#define FRTDS_OFF_PROC              0x016A
#define FRTDS_OFF_STMT              0x01CB
#define FRTDS_OFF_PARAM             0x01C4

#define FRTDS_ALT_AVG               0x4F   //The average value.
#define FRTDS_ALT_COUNT             0x4B   //The summary count value.
#define FRTDS_ALT_MAX               0x52   //The maximum value.
#define FRTDS_ALT_MIN               0x51   //The minimum value.
#define FRTDS_ALT_SUM               0x4D   //The sum value.

#define FRTDS_PARAM                 "PARAMETER"

#define FRTDS_STAT_RENAME           0x20

/*******************************************************************************
*  FUNC     :  Node free
*  ARGS     :  p_st_node(Frlist_node *)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void sybase_datatype_node_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    frfree(p_st_node->data);
    return;
}

/*******************************************************************************
*  FUNC     :  合并字符串
*  ARGS     :  p_first_str(第一个字符串)
*           :  p_second_str(第二个字符串)
*           :  pp_merge_str(合并字符串)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_first_str和p_second_str都不能是NULL
*******************************************************************************/
FR_STATIC int __sybase_merge_string(char *p_first_str
                                 , char *p_second_str
                                 , char **pp_merge_str)
{
    unsigned int ui_len = 0;
    char *p_merge_str = NULL;

    /* 第一个1指的是分隔符[;], 第二个1为了存储字符串结束符[\0] */
    ui_len = strlen(p_first_str) + 1 + strlen(p_second_str) + 1;
    p_merge_str = (char *)frmalloc(ui_len);
    if (p_merge_str == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    snprintf(p_merge_str, ui_len, "%s;%s", p_first_str, p_second_str);
    frfree(p_first_str);
    frfree(p_second_str);

    *pp_merge_str = p_merge_str;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析Data Type
*  ARGS     :  p_st_data(bytebuff数据)
*           :  p_st_session(sybase session信息)
*           :  p_ui_token_len(token长度)
*           :  p_i_data_type(DataType)
*           :  p_ui_len(Length)
*           :  p_ui_precision(precision)
*           :  p_ui_scale(scale)
*           :  p_ui_blob_type(BLOB type)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data肯定不为NULL，且ui_token_len大于1
*******************************************************************************/
static int __sybase_parse_data_type(Frbyte_Packet *p_st_data
                                    , L7session_sybase *p_st_session
                                    , unsigned int *p_ui_token_len
                                    , int *p_i_data_type
                                    , unsigned int *p_ui_len
                                    , unsigned int *p_ui_precision
                                    , unsigned int *p_ui_scale
                                    , unsigned int *p_ui_blob_type)
{
    int i_ret = FR_SUCC;
    uint8_t u8_len = 0;
    uint16_t u16_len = 0;
    uint32_t u32_len = 0;
    uint8_t u8_scale = 0;
    uint8_t u8_data_type = 0;
    uint8_t u8_precision = 0;
    uint8_t u8_blob_type = 0;
    unsigned int ui_len = 0;
    unsigned int ui_token_len = *p_ui_token_len;

    /* 取得DataType */
    bytebuff_get_char(p_st_data, &u8_data_type);
    ui_token_len--;
    /* 根据datatype解析 */
    switch (u8_data_type)
    {
        case FRTDS_BIT:          //Bit
        case FRTDS_DATE:         //Date
        case FRTDS_DATETIME:     //Date/time
        case FRTDS_SHORTDATE:    //Date/time
        case FRTDS_FLT4:         //Float
        case FRTDS_FLT8:         //Float
        case FRTDS_INT1:         //Unsigned Integer
        case FRTDS_INT2:         //Integer
        case FRTDS_INT4:         //Integer
        case FRTDS_INT8:         //Integer
        case FRTDS_INTERVAL:     //Time Interval
        case FRTDS_SINT1:        //Signed Integer
        case FRTDS_UINT2:        //Unsigned Integer
        case FRTDS_UINT4:        //Unsigned Integer
        case FRTDS_UINT8:        //Unsigned Integer
        case FRTDS_MONEY:        //Money
        case FRTDS_SHORTMONEY:   //Money
        case FRTDS_TIME:         //Time
            break;

        case FRTDS_BINARY:       //Binary
        case FRTDS_CHAR:         //Character
        case FRTDS_SENSITIVITY:  //Sensitivity
        case FRTDS_VARBINARY:    //Binary
        case FRTDS_VARCHAR:      //Character
        case FRTDS_BOUNDARY:     //Boundary
            bytebuff_get_char(p_st_data, &u8_len);
            ui_len = u8_len;
            ui_token_len--;
            break;

        case FRTDS_DATEN:        //Date
        case FRTDS_TIMEN:        //Time
            bytebuff_get_char(p_st_data, &u8_len);
            /* FRTDS_DATEN's length is 0 or 4 */
            if (u8_len != 0 && u8_len != 4)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_len = u8_len;
            ui_token_len--;
            break;

        case FRTDS_DATETIMEN:    //Date/time
        case FRTDS_FLTN:         //Float
        case FRTDS_MONEYN:       //Money
            bytebuff_get_char(p_st_data, &u8_len);
            /* FRTDS_DATETIMEN's length is 4 0r 8 */
            /* FRTDS_FLTN's length is 4 0r 8 */
            /* FRTDS_MONEYN's length is 4 0r 8 */
            if (u8_len != 4 && u8_len != 8)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_len = u8_len;
            ui_token_len--;
            break;

        case FRTDS_INTN:         //Integer
        case FRTDS_UINTN:        //Unsigned Integer
            bytebuff_get_char(p_st_data, &u8_len);
            /* FRTDS_INTN's length is 1 or 2 or 4 or 8 */
            switch (u8_len)
            {
                case 1:
                case 2:
                case 4:
                case 8:
                    break;

                default:
                    return APM_L7_ANALYZE_FAIL;
            }
            ui_len = u8_len;
            ui_token_len--;
            break;

        case FRTDS_DECN:         //Decimal
        case FRTDS_NUMN:         //Numeric
            if (ui_token_len < 1 + 1 + 1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_get_char(p_st_data, &u8_len);
            if (u8_len == 0 || u8_len > 33)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_get_char(p_st_data, &u8_precision);
            if (u8_precision == 0 || (u8_len != 255 && u8_len > 77))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_get_char(p_st_data, &u8_scale);
            if (u8_len != 255 && u8_len > 77)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_len = u8_len;
            ui_token_len -= 1 + 1 + 1;
            break;

        case FRTDS_IMAGE:        //Image
        case FRTDS_TEXT:         //Text
        case FRTDS_UNITEXT:      //Unicode UTF-16 Text
        case FRTDS_XML:          //XML
            if (ui_token_len < 4 + 2)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 取得长度 */
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_len
                                    , p_st_session->i_lint4_endian);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_token_len -= 4;
            /* 跳过image name */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_len
                                      , p_st_session->i_lint2_endian);
            if (ui_token_len < (unsigned int)(2 + u16_len))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_skip(p_st_data, u16_len);
            ui_token_len -= 2 + u16_len;
            break;

        case FRTDS_LONGBINARY:   //Binary
        case FRTDS_LONGCHAR:     //Character
            if (ui_token_len < 4)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 取得长度 */
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_len
                                    , p_st_session->i_lint4_endian);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_token_len -= 4;
            break;

        case FRTDS_BLOB:         //Serialized Object
            if (ui_token_len < 1 + 2)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 取得BLOB type */
            bytebuff_get_char(p_st_data, &u8_blob_type);
            switch (u8_blob_type)
            {
                case 0x01:
                case 0x02:
                case 0x03:
                case 0x04:
                case 0x05:
                    break;

                default:
                    return APM_L7_ANALYZE_FAIL;
            }
            /* 跳过class ID */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_len
                                      , p_st_session->i_lint2_endian);
            if (ui_token_len < (unsigned int)(2 + u16_len))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_skip(p_st_data, u16_len);
            ui_token_len -= 3 + u16_len;
            break;

        case FRTDS_VOID:         //Void (unknown)
            frdbg("Therr have unknown date type!\n");
            return APM_L7_ANALYZE_FAIL;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    *p_i_data_type = u8_data_type;
    *p_ui_token_len = ui_token_len;
    *p_ui_precision = u8_precision;
    *p_ui_scale = u8_scale;
    *p_ui_blob_type = u8_blob_type;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  跳过data
*  ARGS     :  p_st_data(bytebuff数据)
*           :  p_st_session(sybase session信息)
*           :  p_st_metadata(metadata信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data和p_st_metadata不为NULL
*******************************************************************************/
static int __sybase_skip_data(Frbyte_Packet *p_st_data
                             , int i_whole_flg
                             , L7session_sybase *p_st_session
                             , Sql_metadata_info *p_st_metadata)
{
    int i_ret = FR_SUCC;
    uint8_t u8_len = 0;
    uint8_t u8_serial_type = 0;
    uint16_t u16_classid_len = 0;
    uint32_t u32_len = 0;
    int i_end_blob = FR_NO;
    unsigned int ui_skip_len = 0;

    switch (p_st_metadata->i_data_type)
    {
        case FRTDS_BINARY:      //Binary
        case FRTDS_BOUNDARY:    //Boundary
        case FRTDS_CHAR:        //Character
        case FRTDS_DECN:        //Decimal
        case FRTDS_NUMN:        //Numeric
        case FRTDS_SENSITIVITY: //Sensitivity
        case FRTDS_VARBINARY:   //Binary
        case FRTDS_VARCHAR:     //Character
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto unknow;
            }
            bytebuff_get_char(p_st_data, &u8_len);
            ui_skip_len = u8_len;
            break;

        case FRTDS_BIT:         //Bit
        case FRTDS_INT1:        //Unsigned Integer
        case FRTDS_SINT1:       //Signed Integer
            ui_skip_len = 1;
            break;

        case FRTDS_INT2:        //Integer
        case FRTDS_UINT2:       //Unsigned Integer
            ui_skip_len = 2;
            break;

        case FRTDS_DATE:        //Date
        case FRTDS_SHORTDATE:   //Date/time
        case FRTDS_FLT4:        //Float
        case FRTDS_INT4:        //Integer
        case FRTDS_UINT4:       //Unsigned Integer
        case FRTDS_SHORTMONEY:  //Money
        case FRTDS_TIME:        //Time
            ui_skip_len = 4;
            break;

        case FRTDS_DATETIME:    //Date/time
        case FRTDS_FLT8:        //Float
        case FRTDS_INT8:        //Integer
        case FRTDS_INTERVAL:    //Time Interval
        case FRTDS_UINT8:       //Unsigned Integer
        case FRTDS_MONEY:       //Money
            ui_skip_len = 8;
            break;

        case FRTDS_DATEN:       //Date
        case FRTDS_TIMEN:       //Time
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto unknow;
            }
            bytebuff_get_char(p_st_data, &u8_len);
            if (u8_len != 0 && u8_len != 4)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_skip_len = u8_len;
            break;

        case FRTDS_DATETIMEN:   //Date/time
        case FRTDS_FLTN:        //Float
        case FRTDS_MONEYN:      //Money
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto unknow;
            }
            bytebuff_get_char(p_st_data, &u8_len);
            if (u8_len != 0 && u8_len != 4 && u8_len != 8)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_skip_len = u8_len;
            break;

        case FRTDS_IMAGE:       //Image
        case FRTDS_TEXT:        //Text
        case FRTDS_UNITEXT:     //Unicode UTF-16 Text
        case FRTDS_XML:         //XML
            /* 跳过txtptr + TimeStamp */
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto unknow;
            }
            bytebuff_get_char(p_st_data, &u8_len);
            if (bytebuff_remaining(p_st_data) < u8_len + 8 + 4)
            {
                goto unknow;
            }
            bytebuff_skip(p_st_data, u8_len + 8);
            /* 跳过DataLen */
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_len
                                    , p_st_session->i_lint4_endian);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_skip_len = u32_len;
            break;

        case FRTDS_INTN:        //Integer
        case FRTDS_UINTN:       //Unsigned Integer
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto unknow;
            }
            bytebuff_get_char(p_st_data, &u8_len);
            switch (u8_len)
            {
                case 0:
                case 1:
                case 2:
                case 4:
                case 8:
                    break;

                default:
                return APM_L7_ANALYZE_FAIL;
            }
            ui_skip_len = u8_len;
            break;

        case FRTDS_LONGBINARY:  //Binary
        case FRTDS_LONGCHAR:    //Character
            if (bytebuff_remaining(p_st_data) < 4)
            {
                goto unknow;
            }
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_len
                                    , p_st_session->i_lint4_endian);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_skip_len = u32_len;
            break;

        case FRTDS_BLOB:        //Serialized Object
            if (bytebuff_remaining(p_st_data) < 1 + 2)
            {
                goto unknow;
            }
            /* 取得SerializationType */
            bytebuff_get_char(p_st_data, &u8_serial_type);
            if (u8_serial_type != 0x00
                && u8_serial_type != 0x01
                && u8_serial_type != 0x02)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 跳过class id */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_classid_len
                                      , p_st_session->i_lint2_endian);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (bytebuff_remaining(p_st_data) < u16_classid_len)
            {
                goto unknow;
            }
            bytebuff_skip(p_st_data, u16_classid_len);

            /* 跳过blob内容 */
            while (i_end_blob == FR_NO)
            {
                if (bytebuff_remaining(p_st_data) < 4)
                {
                    goto unknow;
                }
                i_ret = bytebuff_get_int(p_st_data, 4, &u32_len
                                         , p_st_session->i_lint4_endian);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }

                /*
                *  DataLen is a 4-byte field The high-order bit indicates
                *  whether this is the last (0) DataLen/Data pairs, or if
                *  there is another DataLen value after the Data array (1).
                *  The low-order 31 bytes is an unsigned length of the
                *  following Data array
                */
                if ((u32_len & 0x80000000) == 0)
                {
                    i_end_blob = FR_YES;
                    ui_skip_len = u32_len;
                }
                else
                {
                    ui_skip_len = u32_len & 0x7FFFFFFF;
                }

                if (ui_skip_len < (unsigned int)bytebuff_remaining(p_st_data))
                {
                    bytebuff_skip(p_st_data, ui_skip_len);
                    ui_skip_len = 0;
                }
                else
                {
                    if (i_whole_flg == FR_YES)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                    else
                    {
                        bytebuff_set_skip(p_st_data, ui_skip_len - bytebuff_remaining(p_st_data));
                        return APM_L7_ANALYZE_TODO;
                    }
                }
            }
            break;

        default:
            /* never happen */
            return APM_L7_ANALYZE_FAIL;
    }

    if (ui_skip_len)
    {
        if (ui_skip_len < (unsigned int)bytebuff_remaining(p_st_data))
        {
            bytebuff_skip(p_st_data, ui_skip_len);
            ui_skip_len = 0;
        }
        else
        {
            if (i_whole_flg == FR_YES)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else
            {
                bytebuff_set_skip(p_st_data, ui_skip_len - bytebuff_remaining(p_st_data));
                return APM_L7_ANALYZE_TODO;
            }
        }
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  把DECIMAL的数据转成字符串
*  ARGS     :  pp_inbuffer(入力buffer)
*           :  i_whole_flg(完整flag)
*           :  i_endian(字节序)
*           :  pp_st_value(出力字数据)
*  RTN      :  APM_L7_ANALYZE_SUCC(succ)
*              APM_L7_ANALYZE_TODO(need more data)
*              APM_L7_ANALYZE_FAIl(error)
*  NOTE     : 成功时且i_get_value_flg是TRUE时，使用之后释放pp_st_value内存
*******************************************************************************/
static int __sybase_convert_to_dec(Frbyte_Packet *p_st_data
                                   , int i_whole_flg
                                   , unsigned int i_scale
                                   , LITTLE_BIG_ENDIAN i_endian
                                   , Frdata_field **pp_st_value)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_len = 0;
    unsigned ui_loop = 0;
    unsigned long long ull_value;
    double d_value = 0;
    double d_scale = 0;
    char arr_deciaml[10] = {0};
    char *p_value = NULL;

    /* 数据长度不足 */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        /* 还有本次请求未接收完了的数据 */
        if (i_whole_flg == FR_NO)
        {
            return APM_L7_ANALYZE_TODO;
        }
        else
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }

    bytebuff_get_char(p_st_data, &u8_len);
    /* 解析date */
    if (u8_len)
    {
        /* 数据长度不足 */
        if (bytebuff_remaining(p_st_data) < u8_len)
        {
            /* 还有本次请求未接收完了的数据 */
            if (i_whole_flg == FR_NO)
            {
                return APM_L7_ANALYZE_TODO;
            }
            else
            {
                return APM_L7_ANALYZE_FAIL;
            }
        }
        /*长度大于8的不解析  */
        if (u8_len > 8)
        {
            bytebuff_skip(p_st_data, u8_len);
            //todo 当做NULL
            i_ret = frtds_create_param(NULL, FRFLOAT, pp_st_value);
        }
        else /* 取得decimal */
        {
            i_ret = bytebuff_get_bytes(p_st_data, arr_deciaml, u8_len);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (i_endian == BYTE_LITTLE_ENDIAN)
            {
                while (u8_len--)
                {
                    ull_value = (ull_value << 8) | (unsigned char)arr_deciaml[u8_len];
                }
            }
            else
            {
                while (ui_loop < u8_len)
                {
                    ull_value = (ull_value << 8) | (unsigned char)arr_deciaml[ui_loop++];
                }
            }
            d_value = ull_value;
            d_scale = pow(10, i_scale);
            d_value = d_value/d_scale;
            p_value = (char *)frmalloc(128);
            if (p_value == NULL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            snprintf(p_value, 128, "%lf", d_value);
            i_ret = frtds_create_param(p_value, FRFLOAT, pp_st_value);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                frfree(p_value);
                return APM_L7_ANALYZE_FAIL;
            }
        }
    }
    else
    {
        i_ret = frtds_create_param(NULL, FRFLOAT, pp_st_value);
    }
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  解析取得data
*  ARGS     :  p_st_data(bytebuff数据)
*           :  p_st_session(sybase session信息)
*           :  p_st_metadata(metadata信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data和p_st_metadata不为NULL
*******************************************************************************/
static int __sybase_get_data(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , L7session_sybase *p_st_session
                              , Sql_metadata_info *p_st_metadata
                              , Frdata_field **pp_st_value)
{
    int i_ret = FR_SUCC;
    uint8_t u8_len = 0;
    uint8_t u8_serial_type = 0;
    uint32_t u32_len = 0;
    uint16_t u16_classid_len = 0;
    int i_end_blob = FR_NO;
    unsigned int ui_skip_len = 0;
    char *p_value = NULL;

    switch (p_st_metadata->i_data_type)
    {
        case FRTDS_BIT:         //Bit
            i_ret = frtds_convert_to_boolean(p_st_data, i_whole_flg, pp_st_value);
            break;

        case FRTDS_BOUNDARY:    //Boundary
        case FRTDS_CHAR:        //Character
        case FRTDS_VARCHAR:     //Character
        case FRTDS_SENSITIVITY: //Sensitivity
        case FRTDS_VARBINARY:   //Binary
        case FRTDS_BINARY:      //Binary
            i_ret = frtds_convert_to_varchar(p_st_data, i_whole_flg
                                           , p_st_session->i_lint2_endian
                                           , 1, pp_st_value);
            break;

        case FRTDS_DATE:        //Date
            i_ret = frtds_convert_to_date(p_st_data, 4
                                       , p_st_session->i_lint2_endian
                                       , FRTDS_SYBASE, i_whole_flg, pp_st_value);
            break;

        case FRTDS_DATEN:       //Date
            i_ret = frtds_convert_to_daten(p_st_data, p_st_session->i_lint2_endian
                                        , FRTDS_SYBASE, i_whole_flg, pp_st_value);
            break;

        case FRTDS_SHORTDATE:   //Date/time
            i_ret = frtds_convert_to_datetime(p_st_data, 4
                                            , p_st_session->i_lint2_endian
                                            , i_whole_flg, pp_st_value);
            break;

        case FRTDS_DATETIME:    //Date/time
            i_ret = frtds_convert_to_datetime(p_st_data, 8, p_st_session->i_lint2_endian
                                            , i_whole_flg, pp_st_value);
            break;

        case FRTDS_DATETIMEN:   //Date/time
            i_ret = frtds_convert_to_datetimen(p_st_data, p_st_session->i_lint2_endian
                                             , i_whole_flg, pp_st_value);
            break;

        case FRTDS_FLT4:        //Float
            i_ret = frtds_convert_to_float(p_st_data, 4
                                         , p_st_session->i_lflt4_type
                                         , i_whole_flg, pp_st_value);
            break;

        case FRTDS_FLT8:        //Float
            i_ret = frtds_convert_to_float(p_st_data, 8
                                         , p_st_session->i_lflt_type
                                         , i_whole_flg, pp_st_value);
            break;

        case FRTDS_FLTN:        //Float
            i_ret = frtds_convert_to_floatn(p_st_data, p_st_session->i_lflt_type
                                          , i_whole_flg, pp_st_value);
            break;

        case FRTDS_IMAGE:       //Image
        case FRTDS_TEXT:        //Text
        case FRTDS_UNITEXT:     //Unicode UTF-16 Text
        case FRTDS_XML:         //XML
            /* 跳过txtptr + TimeStamp */
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto unknow;
            }
            bytebuff_get_char(p_st_data, &u8_len);
            if (bytebuff_remaining(p_st_data) < u8_len + 8 + 4)
            {
                goto unknow;
            }
            bytebuff_skip(p_st_data, u8_len + 8);
            /* 跳过DataLen */
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_len
                                    , p_st_session->i_lint4_endian);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* skip data */
            if (u32_len < (unsigned int)bytebuff_remaining(p_st_data))
            {
                bytebuff_skip(p_st_data, u32_len);
                frtds_create_param(frstrdup("TEXT/IMAGE DATA"), FRSTRING, pp_st_value);
            }
            else
            {
                if (i_whole_flg == FR_YES)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    bytebuff_set_skip(p_st_data, u32_len - bytebuff_remaining(p_st_data));
                    return APM_L7_ANALYZE_TODO;
                }
            }
            break;

        case FRTDS_SINT1:       //Signed Integer
            i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                      , p_st_session->i_lint2_endian
                                       , 1, FR_NO, pp_st_value);
            break;

        case FRTDS_INT1:        //Unsigned Integer
            i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                       , p_st_session->i_lint2_endian
                                       , 1, FR_YES, pp_st_value);
            break;

        case FRTDS_INT2:        //Integer
            i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                       , p_st_session->i_lint2_endian
                                       , 2, FR_NO, pp_st_value);
            break;

        case FRTDS_UINT2:       //Unsigned Integer
            i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                       , p_st_session->i_lint2_endian
                                       , 2, FR_YES, pp_st_value);
            break;

        case FRTDS_INT4:        //Integer
            i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                       , p_st_session->i_lint2_endian
                                       , 4, FR_NO, pp_st_value);
            break;

        case FRTDS_UINT4:       //Unsigned Integer
            i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                       , p_st_session->i_lint2_endian
                                       , 4, FR_YES, pp_st_value);
            break;

        case FRTDS_INT8:        //Integer
            i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                       , p_st_session->i_lint2_endian
                                       , 8, FR_NO, pp_st_value);
            break;

        case FRTDS_UINT8:       //Unsigned Integer
        case FRTDS_INTERVAL:    //Time Interval
            i_ret = frtds_convert_to_int(p_st_data, i_whole_flg
                                       , p_st_session->i_lint2_endian
                                       , 8, FR_YES, pp_st_value);
            break;

        case FRTDS_INTN:        //Integer
            i_ret = frtds_convert_to_intn(p_st_data, i_whole_flg
                                       , p_st_session->i_lint2_endian
                                       , FR_NO, pp_st_value);
            break;

        case FRTDS_UINTN:       //Unsigned Integer
            i_ret = frtds_convert_to_intn(p_st_data, i_whole_flg
                                       , p_st_session->i_lint2_endian
                                       , FR_YES, pp_st_value);
            break;

        /* 大数据,不取得具体值 */
        case FRTDS_LONGBINARY:  //Binary
        case FRTDS_LONGCHAR:    //Character
            if (bytebuff_remaining(p_st_data) < 4)
            {
                goto unknow;
            }
            /* 取得长度 */
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_len
                                    , p_st_session->i_lint4_endian);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* skip data */
            if (u32_len < (unsigned int)bytebuff_remaining(p_st_data))
            {
                bytebuff_skip(p_st_data, u32_len);
                frtds_create_param(frstrdup("LOND DATA"), FRSTRING, pp_st_value);
            }
            else
            {
                if (i_whole_flg == FR_YES)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    bytebuff_set_skip(p_st_data, u32_len - bytebuff_remaining(p_st_data));
                    return APM_L7_ANALYZE_TODO;
                }
            }
            break;

        case FRTDS_TIME:        //Time
            i_ret = frtds_convert_to_time(p_st_data, 4, p_st_session->i_lint2_endian
                                         , i_whole_flg, pp_st_value);
            break;

        case FRTDS_TIMEN:       //Time
            i_ret = frtds_convert_to_timen(p_st_data, p_st_session->i_lint2_endian
                                         , i_whole_flg, pp_st_value);
            break;

        case FRTDS_SHORTMONEY:  //Money
            i_ret = frtds_convert_to_money(p_st_data, i_whole_flg
                                          , p_st_session->i_lint2_endian
                                          , 4, pp_st_value);
            break;

        case FRTDS_MONEY:       //Money
            i_ret = frtds_convert_to_money(p_st_data, i_whole_flg
                                          , p_st_session->i_lint2_endian
                                          , 8, pp_st_value);
            break;

        case FRTDS_MONEYN:      //Money
            i_ret = frtds_convert_to_moneyn(p_st_data, i_whole_flg
                                           , p_st_session->i_lint2_endian
                                           , pp_st_value);
            break;

        case FRTDS_DECN:        //Decimal
        case FRTDS_NUMN:        //Numeric
            i_ret = __sybase_convert_to_dec(p_st_data, i_whole_flg
                                           , p_st_metadata->ui_scale
                                           , p_st_session->i_lint2_endian
                                           , pp_st_value);
            break;

        case FRTDS_BLOB:        //Serialized Object
            if (bytebuff_remaining(p_st_data) < 1 + 2)
            {
                goto unknow;
            }
            /* 取得SerializationType */
            bytebuff_get_char(p_st_data, &u8_serial_type);
            if (u8_serial_type != 0x00
                && u8_serial_type != 0x01
                && u8_serial_type != 0x02)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 跳过class id */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_classid_len
                                      , p_st_session->i_lint2_endian);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (bytebuff_remaining(p_st_data) < u16_classid_len)
            {
                goto unknow;
            }
            bytebuff_skip(p_st_data, u16_classid_len);

            /* 跳过blob内容 */
            while (i_end_blob == FR_NO)
            {
                if (bytebuff_remaining(p_st_data) < 4)
                {
                    goto unknow;
                }
                i_ret = bytebuff_get_int(p_st_data, 4, &u32_len
                                         , p_st_session->i_lint4_endian);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }

                /*
                *  DataLen is a 4-byte field The high-order bit indicates
                *  whether this is the last (0) DataLen/Data pairs, or if
                *  there is another DataLen value after the Data array (1).
                *  The low-order 31 bytes is an unsigned length of the
                *  following Data array
                */
                if ((u32_len & 0x80000000) == 0)
                {
                    i_end_blob = FR_YES;
                    ui_skip_len = u32_len;
                }
                else
                {
                    ui_skip_len = u32_len & 0x7FFFFFFF;
                }

                if (ui_skip_len < (unsigned int)bytebuff_remaining(p_st_data))
                {
                    bytebuff_skip(p_st_data, ui_skip_len);
                    ui_skip_len = 0;
                    p_value = frstrdup("BLOB DATA");
                    i_ret = frtds_create_param(p_value, FRBLOB, pp_st_value);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        frfree(p_value);
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                else
                {
                    if (i_whole_flg == FR_YES)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                    else
                    {
                        bytebuff_set_skip(p_st_data, ui_skip_len - bytebuff_remaining(p_st_data));
                        return APM_L7_ANALYZE_TODO;
                    }
                }
            }
            break;

        default:
            /* never happen */
            return APM_L7_ANALYZE_FAIL;
    }

    return i_ret;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  取得login的值
*  ARGS     :  p_st_data(bytebuff数据)
*           :  pp_value(value)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
static int __frdb_get_value(Frbyte_Packet *p_st_data, char **pp_value)
{
    int i_ret = FR_SUCC;
    uint8_t u8_len = 0;
    char *p_value = NULL;
    char arr_buff[FRTDS_MAX_NAME + 1];

    /* 取得value */
    i_ret = bytebuff_get_bytes(p_st_data, arr_buff, FRTDS_MAX_NAME);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得value的长度 */
    i_ret = bytebuff_get_char(p_st_data, &u8_len);
    if (i_ret != FR_SUCC || u8_len > FRTDS_MAX_NAME)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 做成value */
    if (u8_len)
    {
        p_value = (char *)frmalloc(u8_len + 1);
        if (p_value == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        snprintf(p_value, u8_len + 1, "%s", arr_buff);
    }

    /* 出力设置 */
    *pp_value = p_value;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得指定的ValueMask值
*  ARGS     :  p_value_mask(ValueMask)
*           :  ui_mask_len(ValueMask长度)
*           :  ui_index(指定的位置)
*           :  p_i_flg(TRUE/FALSE)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
static void __frdb_get_value_mask(char *p_value_mask
                                  , unsigned int ui_mask_len
                                  , unsigned int ui_index
                                  , int *p_i_flg)
{
    unsigned char uc_mask = 0;
    unsigned int ui_index1 = 0;
    unsigned int ui_index2 = 0;

    ui_index1 = ui_index/8;
    ui_index2 = ui_index%8;
    /* 该指定的MASK不存在 */
    if (ui_index1 >= ui_mask_len)
    {
        *p_i_flg = FR_NO;
        return;
    }

    ui_index1 = ui_mask_len - ui_index1 - 1;
    uc_mask = (unsigned char)p_value_mask[ui_index1];
    if (uc_mask & 1 << ui_index2)
    {
        *p_i_flg = FR_YES;
    }
    else
    {
        *p_i_flg = FR_NO;
    }
    return;
}

/*******************************************************************************
*  FUNC     :  解析LOGIN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(session信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data和p_st_session必须不为NULL
*******************************************************************************/
int sybase_parse_login_token(Frbyte_Packet *p_st_data
                             , int i_whole_flg
                             , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析loginrec =
    *                FRTDS_BYTE(lhostname[FRTDS_MAX_NAME])
    *                FRTDS_BYTE(lhostnlen)
    *                FRTDS_BYTE(lusername[FRTDS_MAX_NAME])
    *                FRTDS_BYTE(lusernlen)
    *                FRTDS_BYTE(lpw[FRTDS_MAX_NAME])
    *                FRTDS_BYTE(lpwnlen)
    *                FRTDS_BYTE(lhostproc[FRTDS_MAX_NAME])
    *                FRTDS_BYTE(lhplen)
    *                FRTDS_BYTE(lint2)
    *                FRTDS_BYTE(lint4)
    *                FRTDS_BYTE(lchar)
    *                FRTDS_BYTE(lflt)
    *                FRTDS_BYTE(ldate)
    *                FRTDS_BYTE(lusedb)
    *                FRTDS_BYTE(ldmpld)
    *                FRTDS_BYTE(linterfacespare)
    *                FRTDS_BYTE(ltype)
    *                FRTDS_BYTE(lbufsize[FRTDS_NETBUF])
    *                FRTDS_BYTE(lspare[3])
    *                FRTDS_BYTE(lappname[FRTDS_MAX_NAME])
    *                FRTDS_BYTE(lappnlen)
    *                FRTDS_BYTE(lservname[FRTDS_MAX_NAME])
    *                FRTDS_BYTE(lservnlen)
    *                FRTDS_BYTE(lrempw[FRTDS_RPLEN])
    *                FRTDS_BYTE(lrempwlen)
    *                FRTDS_BYTE(ltds[FRTDS_VERSIZE])
    *                FRTDS_BYTE(lprogname[FRTDS_PROGNLEN])
    *                FRTDS_BYTE(lprognlen)
    *                FRTDS_BYTE(lprogvers[FRTDS_VERSIZE])
    *                FRTDS_BYTE(lnoshort)
    *                FRTDS_BYTE(lflt4)
    *                FRTDS_BYTE(ldate4)
    *                FRTDS_BYTE(llanguage[FRTDS_MAX_NAME])
    *                FRTDS_BYTE(llanglen)
    *                FRTDS_BYTE(lsetlang)
    *                FRTDS_BYTE(loldsecure[FRTDS_OLDSECURE])
    *                FRTDS_BYTE(lseclogin)
    *                FRTDS_BYTE(lsecbulk)
    *                FRTDS_BYTE(lhalogin)
    *                FRTDS_BYTE(lhasessionid[FRTDS_HA])
    *                FRTDS_BYTE(lsecspare[FRTDS_SECURE])
    *                FRTDS_BYTE(lcharset[FRTDS_MAX_NAME])
    *                FRTDS_BYTE(lcharsetlen)
    *                FRTDS_BYTE(lsetcharset)
    *                FRTDS_BYTE(lpacketsize[FRTDS_PKTLEN])
    *                FRTDS_BYTE(lpacketsizelen)
    *                FRTDS_BYTE(ldummy[4])
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    //uint8_t u8_len = 0;
    uint8_t u8_lint2 = 0;
    uint8_t u8_lint4 = 0;
    uint8_t u8_lchar = 0;
    uint8_t u8_lflt = 0;
    uint8_t u8_ldate = 0;
    uint8_t u8_lnoshort = 0;
    uint8_t u8_lflt4 = 0;
    uint8_t u8_ldate4 = 0;
    LITTLE_BIG_ENDIAN i_lint2_endian = BYTE_BIG_ENDIAN;
    LITTLE_BIG_ENDIAN i_lint4_endian = BYTE_BIG_ENDIAN;
    Frtds_type_float i_lflt_type = FRTDS_FLT_IEEE_HI;
    LITTLE_BIG_ENDIAN i_ldate_endian = BYTE_BIG_ENDIAN;
    int i_lnoshort_type = 0;
    Frtds_type_float i_lflt4_type = FRTDS_FLT_IEEE_HI;
    LITTLE_BIG_ENDIAN i_ldate4_endian = BYTE_BIG_ENDIAN;
    char *p_host_name = NULL;
    char *p_user_name = NULL;
    char *p_app_name = NULL;
    char *p_charset = NULL;

    /* LOGIN信息里没有长数据,取完整后再解析 */
    if (i_whole_flg == FR_NO)
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得HOST NAME */
    i_ret = __frdb_get_value(p_st_data, &p_host_name);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得USER NAME */
    i_ret = __frdb_get_value(p_st_data, &p_user_name);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        goto error;
    }
    /* skip password and Process identifier */
    i_ret = bytebuff_skip(p_st_data, 2 * (FRTDS_MAX_NAME + 1));
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* get lint2 */
    i_ret = bytebuff_get_char(p_st_data, &u8_lint2);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* get lint4 */
    i_ret = bytebuff_get_char(p_st_data, &u8_lint4);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* get lchar */
    i_ret = bytebuff_get_char(p_st_data, &u8_lchar);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* get lflt */
    i_ret = bytebuff_get_char(p_st_data, &u8_lflt);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* get ldate */
    i_ret = bytebuff_get_char(p_st_data, &u8_ldate);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* skip lusedb, ldmpld, linterfacespare, ltype, lbufsize, lspare */
    i_ret = bytebuff_skip(p_st_data, 1 + 1 + 1 + 1 + FRTDS_NETBUF + 3);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* 取得APP NAME */
    i_ret = __frdb_get_value(p_st_data, &p_app_name);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        goto error;
    }
    /* skip lservname, lrempw, ltds, lprogname, lprogvers */
    i_ret = bytebuff_skip(p_st_data, FRTDS_MAX_NAME + 1 + FRTDS_RPLEN + 1
                          + FRTDS_VERSIZE + FRTDS_PROGNLEN + 1 + FRTDS_VERSIZE);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* get lnoshort */
    i_ret = bytebuff_get_char(p_st_data, &u8_lnoshort);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* get lflt4 */
    i_ret = bytebuff_get_char(p_st_data, &u8_lflt4);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* get ldate4 */
    i_ret = bytebuff_get_char(p_st_data, &u8_ldate4);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /*
    *  skip llanguage, lsetlang, loldsecure, lseclogin,
    *  lsecbulk, lhalogin, lhasessionid, lsecspare
    */
    i_ret = bytebuff_skip(p_st_data, FRTDS_MAX_NAME + 1 + 1 + FRTDS_OLDSECURE
                          + 1 + 1 + 1 + FRTDS_HA + FRTDS_SECURE);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* get lcharset */
    i_ret = __frdb_get_value(p_st_data, &p_charset);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* skip lsetcharset, lpacketsize, lpacketsizelen, ldummy */
    i_ret = bytebuff_skip(p_st_data, 1 + FRTDS_PKTLEN + 1 + 4);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }

    /* check login information */
    /* check lint2 */
    switch (u8_lint2)
    {
        case 2: //FRTDS_INT2_LSB_HI
            i_lint2_endian = BYTE_BIG_ENDIAN;
            break;

        case 3: //FRTDS_INT2_LSB_LO
            i_lint2_endian = BYTE_LITTLE_ENDIAN;
            break;

        default:
            goto error;
    }
    /* check lint4 */
    switch (u8_lint4)
    {
        case 0: //FRTDS_INT2_LSB_HI
            i_lint4_endian = BYTE_BIG_ENDIAN;
            break;

        case 1: //FRTDS_INT2_LSB_LO
            i_lint4_endian = BYTE_LITTLE_ENDIAN;
            break;

        default:
            goto error;
    }
    /* check lchar */
    switch (u8_lchar)
    {
        case 6: //FRTDS_CHAR_ASCII
            /* 设置默认的charset为UTF-8 */
            if (p_charset == NULL)
            {
                p_charset = frstrdup("UTF-8");
                if (p_charset == NULL)
                {
                    goto error;
                }
            }
            break;

        case 7: //FRTDS_CHAR_EBCDIC
            /*  */
            if (p_charset)
            {
                frfree(p_charset);
            }
            /*
            *  FRTDS_CHAR_EBCDIC indicates that the EBCDIC(CP500) character
            *  set is being used by the client
            */
            p_charset = frstrdup("CP500");
            if (p_charset == NULL)
            {
                goto error;
            }
            break;

        default:
            goto error;
    }
    /* check lflt */
    switch (u8_lflt)
    {
        case 4:  //FRTDS_FLT_IEEE_HI(4)
            i_lflt_type = FRTDS_FLT_IEEE_HI;
            break;

        case 5:  //FRTDS_FLT_VAXD(5)
            i_lflt_type = FRTDS_FLT_VAXD;
            break;

        case 10: //FRTDS_FLT_IEEE_LO(10)
            i_lflt_type = FRTDS_FLT_IEEE_LO;
            break;

        case 11: //FRTDS_FLT_ND5000(11)
            i_lflt_type = FRTDS_FLT_ND5000;
            break;

        default:
            goto error;
    }
    /* check ldate */
    switch (u8_ldate)
    {
        case 8: //FRTDS_TWO_I4_LSB_HI
            i_ldate_endian = BYTE_BIG_ENDIAN;
            break;

        case 9: //FRTDS_TWO_I4_LSB_LO
            i_ldate_endian = BYTE_LITTLE_ENDIAN;
            break;

        default:
            goto error;
    }
    /* check lnoshort */
    switch (u8_lnoshort)
    {
        case 0: //FRTDS_NOCVT_SHORT(0)
            i_lnoshort_type = FRTDS_NOCVT_SHORT;
            break;

        case 1: //FRTDS_CVT_SHORT
            i_lnoshort_type = FRTDS_NOCVT_SHORT;
            break;

        default:
            goto error;
    }
    /* check lflt4 */
    switch (u8_lflt4)
    {
        case 12:  //FRTDS_FLT_IEEE_HI(4)
            i_lflt4_type = FRTDS_FLT_IEEE_HI;
            break;

        case 13:  //FRTDS_FLT_VAXD(5)
            i_lflt4_type = FRTDS_FLT_VAXD;
            break;

        case 14: //FRTDS_FLT_IEEE_LO(10)
            i_lflt4_type = FRTDS_FLT_IEEE_LO;
            break;

        case 15: //FRTDS_FLT_ND5000(11)
            i_lflt4_type = FRTDS_FLT_ND5000;
            break;

        default:
            goto error;
    }
    /* check ldate4 */
    switch (u8_ldate4)
    {
        case 16: //FRTDS_TWO_I4_LSB_HI
            i_ldate4_endian = BYTE_BIG_ENDIAN;
            break;

        case 17: //FRTDS_TWO_I4_LSB_LO
            i_ldate4_endian = BYTE_LITTLE_ENDIAN;
            break;

        default:
            goto error;
    }

    /* 设置session数据 */
    /* host name */
    if (p_st_session->p_cli_host_user)
    {
        frfree(p_st_session->p_cli_host_user);
    }
    p_st_session->p_cli_host_user = p_host_name;
    /* program name */
    if (p_st_session->p_program)
    {
        frfree(p_st_session->p_program);
    }
    p_st_session->p_program = p_app_name;
    /* user name */
    if (p_st_session->p_db_user)
    {
        frfree(p_st_session->p_db_user);
    }
    p_st_session->p_db_user = p_user_name;
    /* charset */
    if (p_st_session->p_tds_charset)
    {
        frfree(p_st_session->p_tds_charset);
    }
    p_st_session->p_tds_charset = p_charset;
    /* other */
    p_st_session->i_lint2_endian = i_lint2_endian;
    p_st_session->i_lint4_endian = i_lint4_endian;
    p_st_session->i_lflt_type = i_lflt_type;
    p_st_session->i_ldate_endian = i_ldate_endian;
    p_st_session->i_lnoshort_type = i_lnoshort_type;
    p_st_session->i_lflt4_type = i_lflt4_type;
    p_st_session->i_ldate4_endian = i_ldate4_endian;
    return APM_L7_ANALYZE_SUCC;

error:
    if (p_host_name)
        frfree(p_host_name);
    if (p_user_name)
        frfree(p_user_name);
    if (p_app_name)
        frfree(p_app_name);
    if (p_charset)
        frfree(p_charset);

    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ALTFMT TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_lst_altfmt(ALTFMT信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data和p_lst_altfmt必须不为NULL
*******************************************************************************/
int sybase_parse_altfmt_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , L7session_sybase *p_st_session
                              , Frlist_header *p_lst_altfmt)
{
    printf("\n\nsybase_parse_altfmt_token\n\n");
    /* 定义
    * 解析FRTDS_ALTFMT = 0xA8
    *                  Length(2byte unsigned integer)
    *                  ID(2byte unsigned integer)
    *                  #Ops(1byte unsigned integer)
    *                  OpType(1byte unsigned integer)
    *                  OpCol#(1byte unsigned integer)
    *                  UserType(4byte unsigned integer)
    *                  DataType(1byte unsigned integer)
    *                  Length
    *                  LocaleLen(1byte unsigned integer)
    *                  LocalInfo
    *                  #ByCols(1byte unsigned integer)
    *                  Col#(1byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint16_t u16_token_len = 0;
    uint16_t u16_id = 0;
    uint8_t u8_ops = 0;
    uint8_t u8_op_type = 0;
    //uint8_t u8_data_type = 0;
    uint8_t u8_locale_len = 0;
    uint8_t u8_by_cols = 0;
    int i_data_type = 0;
    unsigned int ui_len = 0;
    unsigned int ui_scale = 0;
    unsigned int ui_precision = 0;
    unsigned int ui_token_len = 0;
    unsigned int ui_blob_type = 0;
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;
    Sybase_altfmt *p_sybase_altfmt = NULL;
    Frlist_header *p_lst_metadata = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 2 + 1)
    {
        goto unknow;
    }

    /* 取得FRTDS_ALTFMT的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 2 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_ALTFMT的ID */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_id
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得FRTDS_ALTFMT的#Ops */
    bytebuff_get_char(p_st_data, &u8_ops);
    u16_token_len -= 2 + 1;
    /* 创建头结点 */
    p_lst_metadata = frlist_create();
    if (p_lst_metadata == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    while (u16_token_len)
    {
        if (u8_ops-- == 0)
        {
            break;
        }
        /* OpType + OpCol# + UserType + DataType + LocaleLen */
        if (u16_token_len < 1 + 1 + 4 + 1 + 1)
        {
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得OpType */
        bytebuff_get_char(p_st_data, &u8_op_type);
        switch (u8_op_type)
        {
            case FRTDS_ALT_AVG:
            case FRTDS_ALT_COUNT:
            case FRTDS_ALT_MAX:
            case FRTDS_ALT_MIN:
            case FRTDS_ALT_SUM:
                break;

            default:
                frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                return APM_L7_ANALYZE_FAIL;
        }
        /* 跳过OpCol# + UserType */
        bytebuff_skip(p_st_data, 1 + 4);
        u16_token_len -= 1 + 1 + 4;
        i_ret = __sybase_parse_data_type(p_st_data, p_st_session, &ui_token_len
                                        , &i_data_type, &ui_len, &ui_precision
                                        , &ui_scale, &ui_blob_type);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return i_ret;
        }

        /* 跳过local information */
        if (ui_token_len < 1)
        {
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_get_char(p_st_data, &u8_locale_len);
        if (ui_token_len < (unsigned int)(1 + u8_locale_len))
        {
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_locale_len);
        ui_token_len -= 1 + u8_locale_len;

        /* 创建节点 */
        p_st_metadata = (Sql_metadata_info *)frmalloc(sizeof(Sql_metadata_info));
        if (p_st_metadata == NULL)
        {
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_st_metadata, 0x0, sizeof(Sql_metadata_info));
        p_st_metadata->i_data_type = i_data_type;     /* 数据类型 */
        p_st_metadata->ui_len = ui_len;               /* 数据长度 */
        p_st_metadata->ui_precision = ui_precision;   /* precision */
        p_st_metadata->ui_scale = ui_scale;           /* scale */
        p_st_metadata->i_status = 0;                  /* status */
        p_st_node = frlist_node_create(p_st_metadata);
        if (p_st_node == NULL)
        {
            frfree(p_st_metadata);
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        frlist_push(p_lst_metadata, p_st_node);
    }

    if (u16_token_len < 0)
    {
        frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得FRTDS_ALTFMT的#ByCols */
    bytebuff_get_char(p_st_data, &u8_by_cols);
    if (u16_token_len != 1 + u8_by_cols)
    {
        frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_by_cols);

    /* 创建节点 */
    p_sybase_altfmt = (Sybase_altfmt *)frmalloc(sizeof(Sybase_altfmt));
    if (p_sybase_altfmt == NULL)
    {
        frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
        return APM_L7_ANALYZE_FAIL;
    }
    p_sybase_altfmt->i_id = u16_id;
    p_sybase_altfmt->p_lst_data_type = p_lst_metadata;

    p_st_node = frlist_node_create(p_lst_metadata);
    if (p_st_node == NULL)
    {
        frfree(p_lst_metadata);
        frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
        return APM_L7_ANALYZE_FAIL;
    }
    /* 追加节点 */
    frlist_push(p_lst_altfmt, p_st_node);

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ALTNAME TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_altname_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_ALTNAME = 0xA7
    *                   Length(2byte unsigned integer)
    *                   ID(2byte unsigned integer)
    *                   NameLen(1byte unsigned integer)
    *                   name
    */
    int i_ret = FR_SUCC;
    uint8_t u16_name_len = 0;
    uint16_t u16_token_len = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_ALTNAME的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }
    /* 跳过ID */
    bytebuff_skip(p_st_data, 2);
    u16_token_len -= 2;

    while (u16_token_len)
    {
        /* 跳过name */
        bytebuff_get_char(p_st_data, &u16_name_len);
        if (u16_token_len < 1 + u16_name_len)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u16_name_len);
        u16_token_len-= 1 + u16_name_len;
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ALTROW TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_lst_altfmt(altfmt信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data和p_lst_altfmt必须不为NULL
*******************************************************************************/
int sybase_parse_altrow_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , L7session_sybase *p_st_session
                              , Frlist_header *p_lst_altfmt)
{
    /* 定义
    * 解析FRTDS_ALTROW = 0xD3
    *                  ID(2byte unsigned integer)
    *                  DateLen
    *                  Data
    */
    int i_ret = FR_SUCC;
    //int i_end_blob = FR_NO;
    //uint8_t u8_len = 0;
    //uint8_t u8_serial_type = 0;
    //uint16_t u16_classid_len = 0;
    //uint32_t u32_len = 0;
    uint16_t u16_id = 0;
    //int i_data_type = 0;
    //unsigned int ui_skip_len = 0;
    Frlist_header *p_lst_header = NULL;
    Frlist_node *p_st_node = NULL;
    Sybase_altfmt *p_sybase_altfmt = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        goto unknow;
    }

    /* 取得ID */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_id
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 根据id取得对应的ALTFMT */
    p_st_node = FRLIST_FIRST_NODE(p_lst_altfmt);
    while (p_st_node)
    {
        p_sybase_altfmt = (Sybase_altfmt *)FRLIST_GET_NODE_DATA(p_st_node);
        if (p_sybase_altfmt && p_sybase_altfmt->i_id == u16_id)
        {
            break;
        }
        p_sybase_altfmt = NULL;
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }
    if (p_sybase_altfmt == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_lst_header = p_sybase_altfmt->p_lst_data_type;

    /* 根据ALTFMT解析,response结果不取值 */
    p_st_node = FRLIST_FIRST_NODE(p_lst_header);
    while (p_st_node)
    {
        p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
        /* 跳过data */
        i_ret = __sybase_skip_data(p_st_data, i_whole_flg
                                  , p_st_session, p_st_metadata);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("Call __sybase_skip_data failed\n");
            return i_ret;
        }

        /* 取得下一个DataType */
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CAPABILITY TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  i_req_resp(请求/响应)
*           :  p_st_session(session信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_capability_token(Frbyte_Packet *p_st_data
                                  , int i_whole_flg
                                  , int i_req_resp
                                  , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_CAPABILITY = 0xE2
    *                      Length(2byte unsigned integer)
    *                      Type(1byte unsigned integer)
    *                      TypeLen(1byte unsigned integer)
    *                      ValueMask
    */
    int i_ret = FR_SUCC;
    //int i_end_blob = FR_NO;
    uint8_t u8_type = 0;
    uint8_t u8_type_len = 0;
    uint16_t u16_len = 0;
    int i_columnstatus = 0;
    int i_nocolumnstatus = 0;
    char *p_value_mask = NULL;

    /* DIALOG信息里没有长数据,取完整后再解析 */
    if (i_whole_flg == FR_NO)
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得FRTDS_CAPABILITY的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    while (u16_len)
    {
        /* 取得Type */
        i_ret = bytebuff_get_char(p_st_data, &u8_type);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        u16_len--;
        /* 取得TypeLen */
        i_ret = bytebuff_get_char(p_st_data, &u8_type_len);
        if (i_ret != FR_SUCC || u16_len < 1 + u8_type_len)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        u16_len -= 1 + u8_type_len;
        p_value_mask = (char *)frmalloc(u8_type_len);
        if (p_value_mask == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 解析ValueMask */
        i_ret = bytebuff_get_bytes(p_st_data, p_value_mask, u8_type_len);
        if (i_ret != FR_SUCC)
        {
            frfree(p_value_mask);
            return APM_L7_ANALYZE_FAIL;
        }
        switch (u8_type)
        {
            case FRTDS_CAP_REQUEST:
                /* get FRTDS_DATA_COLUMNSTATUS */
                __frdb_get_value_mask(p_value_mask, u8_type_len
                                     , FRTDS_DATA_COLUMNSTATUS
                                     , &i_columnstatus);
                break;

            case FRTDS_CAP_RESPONSE:
                __frdb_get_value_mask(p_value_mask, u8_type_len
                                     , FRTDS_DATA_NOCOLUMNSTATUS
                                     , &i_nocolumnstatus);
                break;

            default:
                frfree(p_value_mask);
                return APM_L7_ANALYZE_FAIL;
        }
        frfree(p_value_mask);
        p_value_mask = NULL;
    }

    /* 设置信息 */
    if (p_st_session)
    {
        p_st_session->i_columnstatus = i_columnstatus;
        p_st_session->i_nocolumnstatus = i_nocolumnstatus;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_COLINFO TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_colinfo_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_COLINFO = 0xA5
    *                    Length(2byte unsigned integer)
    *                    Column#(1byte unsigned integer)
    *                    Table#(1byte unsigned integer)
    *                    Status(1byte unsigned integer)
    *                    ColLength(1byte unsigned integer)
    *                    ColumnName
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    uint8_t u8_col_len = 0;
    uint16_t u16_token_len = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_COLINFO的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* TODO 为了提高性能可以不做具体的内容check,直接skip */
    //bytebuff_skip(p_st_data, u16_token_len);
    //return APM_L7_ANALYZE_SUCC;

    while (u16_token_len)
    {
        /* Column# + Table# + Status */
        if (u16_token_len < 1 + 1 + 1)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* skip Column# + Table# */
        bytebuff_skip(p_st_data, 2);
        /* get status */
        bytebuff_get_char(p_st_data, &u8_status);
        u16_token_len -= 3;
        /* check status */
        if (u8_status & 0xC3)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /*
        *  ColLength field and the following column name field will appear
        *  only if the preceding Status field has FRTDS_STAT_RENAME set
        */
        else if (u8_status & FRTDS_STAT_RENAME)
        {
            if (u16_token_len < 1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* skip column name */
            bytebuff_get_char(p_st_data, &u8_col_len);
            if (u16_token_len < 1 + u8_col_len)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_skip(p_st_data, u8_col_len);
            u16_token_len -= 1 + u8_col_len;
        }
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_COLINFO2 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_colinfo2_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_COLINFO2 = 0x20
    *                    Length(4byte unsigned integer)
    *                    Column#(1byte unsigned integer)
    *                    Table#(1byte unsigned integer)
    *                    Status(1byte unsigned integer)
    *                    ColLength(1byte unsigned integer)
    *                    ColumnName
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    uint8_t u8_col_len = 0;
    uint32_t u32_token_len = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 4)
    {
        goto unknow;
    }

    /* 取得FRTDS_COLINFO的总长度Length */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_token_len
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (u32_token_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto unknow;
    }

    /* TODO 为了提高性能可以不做具体的内容check,直接skip */
    //bytebuff_skip(p_st_data, u32_token_len);
    //return APM_L7_ANALYZE_SUCC;

    while (u32_token_len)
    {
        /* Column# + Table# + Status */
        if (u32_token_len < 1 + 1 + 1)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* skip Column# + Table# */
        bytebuff_skip(p_st_data, 2);
        /* get status */
        bytebuff_get_char(p_st_data, &u8_status);
        u32_token_len -= 3;
        /* check status */
        if (u8_status & 0xC3)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /*
        *  ColLength field and the following column name field will appear
        *  only if the preceding Status field has FRTDS_STAT_RENAME set
        */
        else if (u8_status & FRTDS_STAT_RENAME)
        {
            if (u32_token_len < 1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* skip column name */
            bytebuff_get_char(p_st_data, &u8_col_len);
            if (u32_token_len < (unsigned int)(1 + u8_col_len))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_skip(p_st_data, u8_col_len);
            u32_token_len -= 1 + u8_col_len;
        }
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CONTROL TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_control_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_CONTROL = 0xAE
    *                   Length(2byte unsigned integer)
    *                   FmtLen(1byte unsigned integer)
    *                   Fmt
    */
    int i_ret = FR_SUCC;
    uint8_t u8_fmt_len = 0;
    uint16_t u16_token_len = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_COLINFO的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* TODO 为了提高性能可以不做具体的内容check,直接skip */
    //bytebuff_skip(p_st_data, u16_token_len);
    //return APM_L7_ANALYZE_SUCC;

    while (u16_token_len)
    {
        /* skip fmt */
        bytebuff_get_char(p_st_data, &u8_fmt_len);
        if (u16_token_len < 1 + u8_fmt_len)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_fmt_len);
        u16_token_len -= 1 + u8_fmt_len;
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURCLOSE TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_l_cursor_id(close的游标ID)
*           :  p_cursor_name(close的游标名称)
*           :  p_i_declare_flg(是否需要删除游标标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curclose_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , long *p_l_cursor_id
                               , char *p_cursor_name
                               , int *p_i_declare_flg)
{
    /* 定义
    * 解析FRTDS_CURCLOSE = 0x80
    *                    Length(2byte unsigned integer)
    *                    CursorId(4byte unsigned integer)
    *                    NameLength(1byte unsigned integer)
    *                    CursorName(NameLength)
    *                    Options(1byte)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_options = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;
    uint32_t u32_cursor_id = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURCLOSE的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURCLOSE的CursorId */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_cursor_id
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 4;

    /* NameLength and CursorName are only included if CursorId is equal to 0 */
    if (u32_cursor_id == 0)
    {
        /* 取得FRTDS_CURCLOSE的NameLength */
        bytebuff_get_char(p_st_data, &u8_name_len);
        /* NameLength must be > 0 and <= FRTDS_MAX_NAME(30) */
        if (u8_name_len == 0 || u8_name_len > FRTDS_MAX_NAME
            || u16_token_len != 1 + u8_name_len + 1)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得FRTDS_CURCLOSE的CursorName */
        i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_cursor_name[u8_name_len] = '\0';
    }
    else if (u16_token_len != 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得FRTDS_CURCLOSE的Options */
    bytebuff_get_char(p_st_data, &u8_options);
    if (u8_options != 0 && u8_options != 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    *p_i_declare_flg = u8_options;
    *p_l_cursor_id = u32_cursor_id;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURDECLARE TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_cursor_name(close的游标名称)
*           :  pp_statement(sql statement)
*           :  p_cursor_name(cursor name)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curdeclare_token(Frbyte_Packet *p_st_data
                                  , int i_whole_flg
                                  , L7session_sybase *p_st_session
                                  , int *p_i_status
                                  , char **pp_statement
                                  , char *p_cursor_name)
{
    /* 定义
    * 解析解析FRTDS_CURDECLARE = 0x83
    *                          Length(2byte unsigned integer)
    *                          NameLen(1byte unsigned integer)
    *                          CursorName
    *                          Options(1byte)
    *                          Status(1byte)
    *                          StmtLength(2byte unsigned integer)
    *                          Statement
    *                          #Columns(1byte unsigned integer)
    *                          ColNameLength(1byte unsigned integer)
    *                          ColumnName
    */
    int i_ret = FR_SUCC;
    uint8_t u8_options = 0;
    uint8_t u8_status = 0;
    uint8_t u8_name_len = 0;
    uint8_t u8_columns = 0;
    uint8_t u8_col_len = 0;
    uint16_t u16_token_len = 0;
    uint16_t u16_statement_len = 0;
    char *p_statement = NULL;
    char *p_statement_tmp = NULL;

    /* 基本格式检查(Length + NameLen + Options + Status + StmtLength + Columns)*/
    if (bytebuff_remaining(p_st_data) < 2 + 1 + 1 + 1 + 2 + 1)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURCLOSE的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 1 + 1 + 1 + 2 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURCLOSE的NameLen */
    bytebuff_get_char(p_st_data, &u8_name_len);
    /* a maximum length of FRTDS_MAX_NAME (30) is widely supported */
    if (u8_name_len > FRTDS_MAX_NAME
        || u16_token_len < 1 + u8_name_len + 1 + 1 + 2 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* get cursor name */
    i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_cursor_name[u8_name_len] = '\0';
    /* 取得options */
    bytebuff_get_char(p_st_data, &u8_options);
    /* Cursor option values is 0x00,0x01,x02,0x04,0x08,0x10 */
    if (u8_options & 0xE0)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status & 0xFE)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 更新token length */
    u16_token_len -= 1 + u8_name_len + 1 + 1;

    /* 取得StmtLength */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_statement_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 2 + u16_statement_len + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得statement */
    p_statement = (char *)frmalloc(u16_statement_len + 1);
    if (p_statement == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_statement, u16_statement_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_statement);
        return APM_L7_ANALYZE_FAIL;
    }
    p_statement[u16_statement_len] = '\0';
    u16_token_len -= 2 + u16_statement_len;

    /* 取得#Columns */
    bytebuff_get_char(p_st_data, &u8_columns);
    u16_token_len--;
    if (u8_columns)
    {
        frdbg("Plesase attention to this packet\n");
        while (u8_columns)
        {
            u8_columns--;
            if (u16_token_len == 0)
            {
                frfree(p_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_get_char(p_st_data, &u8_col_len);
            if (u16_token_len < 1 + u8_col_len)
            {
                frfree(p_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            /* 跳过ColumnName */
            bytebuff_skip(p_st_data, u8_col_len);
            u16_token_len -= 1 + u8_col_len;
        }
    }

    /* 只剩下最后1字节的#Columns */
    if (u16_token_len)
    {
        frfree(p_statement);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置出力 */
    *p_i_status = u8_status;
    if (*pp_statement)
    {
        frdbg("Allrady get sql[%s] before\n", *pp_statement);
        /* 合并sql,实际情况应该不会发生 */
        i_ret = __sybase_merge_string(*pp_statement, p_statement, &p_statement_tmp);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frfree(p_statement);
            return APM_L7_ANALYZE_FAIL;
        }
        p_statement = p_statement_tmp;
    }
    *pp_statement = p_statement;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURDECLARE2 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_cursor_name(close的游标名称)
*           :  pp_statement(sql statement)
*           :  p_cursor_name(cursor name)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curdeclare2_token(Frbyte_Packet *p_st_data
                                  , int i_whole_flg
                                  , L7session_sybase *p_st_session
                                  , int *p_i_status
                                  , char **pp_statement
                                  , char *p_cursor_name)
{
    /* 定义
    * 解析解析FRTDS_CURDECLARE = 0x23
    *                          Length(4byte unsigned integer)
    *                          NameLen(1byte unsigned integer)
    *                          CursorName
    *                          Options(1byte)
    *                          Status(1byte)
    *                          StmtLength(4byte unsigned integer)
    *                          Statement
    *                          #Columns(2byte unsigned integer)
    *                          ColNameLength(1byte unsigned integer)
    *                          ColumnName
    */
    int i_ret = FR_SUCC;
    uint8_t u8_options = 0;
    uint8_t u8_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_columns = 0;
    uint8_t u8_col_len = 0;
    uint32_t u32_token_len = 0;
    uint32_t u32_statement_len = 0;
    char *p_statement = NULL;
    char *p_statement_tmp = NULL;

    /* 基本格式检查(Length + NameLen + Options + Status + StmtLength + Columns) */
    if (bytebuff_remaining(p_st_data) < 4 + 1 + 1 + 1 + 4 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURCLOSE的总长度Length */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_token_len
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC || u32_token_len < 1 + 1 + 1 + 4 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (u32_token_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto unknow;
    }

    /* 取得FRTDS_CURCLOSE的NameLen */
    bytebuff_get_char(p_st_data, &u8_name_len);
    /* a maximum length of FRTDS_MAX_NAME (30) is widely supported */
    if (u8_name_len > FRTDS_MAX_NAME
        || u32_token_len <= (unsigned int)(1 + u8_name_len + 1 + 1 + 4 + 2))
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* get cursor name */
    i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_cursor_name[u8_name_len] = '\0';

    /* 取得options */
    bytebuff_get_char(p_st_data, &u8_options);
    /* Cursor option values is 0x00,0x01,x02,0x04,0x08,0x10 */
    if (u8_options & 0xE0)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status & 0xFE)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 更新token length */
    u32_token_len -= 1 + u8_name_len + 1 + 1;

    /* 取得StmtLength */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_statement_len
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC || u32_token_len < 4 + u32_statement_len + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得statement */
    p_statement = (char *)frmalloc(u32_statement_len + 1);
    if (p_statement == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_statement, u32_statement_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_statement);
        return APM_L7_ANALYZE_FAIL;
    }
    p_statement[u32_statement_len] = '\0';
    u32_token_len -= 4 + u32_statement_len;

    /* 取得#Columns */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_columns
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        frfree(p_statement);
        return APM_L7_ANALYZE_FAIL;
    }
    u32_token_len -= 2;
    /* check #Columns */
    if (u16_columns)
    {
        frdbg("Plesase attention to this packet\n");
        while (u16_columns)
        {
            u16_columns--;
            if (u32_token_len == 0)
            {
                frfree(p_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_get_char(p_st_data, &u8_col_len);
            if (u32_token_len < (unsigned int)(1 + u8_col_len))
            {
                frfree(p_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            /* 跳过ColumnName */
            bytebuff_skip(p_st_data, u8_col_len);
            u32_token_len -= 1 + u8_col_len;
        }
    }

    /* 只剩下最后1字节的#Columns */
    if (u32_token_len)
    {
        frfree(p_statement);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置出力 */
    *p_i_status = u8_status;
    if (*pp_statement)
    {
        frdbg("Allrady get sql[%s] before\n", *pp_statement);
        /* 合并sql,实际情况应该不会发生 */
        i_ret = __sybase_merge_string(*pp_statement, p_statement, &p_statement_tmp);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frfree(p_statement);
            return APM_L7_ANALYZE_FAIL;
        }
        p_statement = p_statement_tmp;
    }
    *pp_statement = p_statement;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURDECLARE3 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_cursor_name(close的游标名称)
*           :  pp_statement(sql statement)
*           :  p_cursor_name(cursor name)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curdeclare3_token(Frbyte_Packet *p_st_data
                                  , int i_whole_flg
                                  , L7session_sybase *p_st_session
                                  , int *p_i_status
                                  , char **pp_statement
                                  , char *p_cursor_name)
{
    /* 定义
    * 解析解析FRTDS_CURDECLARE = 0x10
    *                          Length(4byte unsigned integer)
    *                          NameLen(1byte unsigned integer)
    *                          CursorName
    *                          Options(4byte unsigned integer)
    *                          Status(1byte)
    *                          StmtLength(4byte unsigned integer)
    *                          Statement
    *                          #Columns(2byte unsigned integer)
    *                          ColNameLength(1byte unsigned integer)
    *                          ColumnName
    */
    int i_ret = FR_SUCC;
    uint32_t u32_options = 0;
    uint8_t u8_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_columns = 0;
    uint8_t u8_col_len = 0;
    uint32_t u32_token_len = 0;
    uint32_t u32_statement_len = 0;
    char *p_statement = NULL;
    char *p_statement_tmp = NULL;

    /* 基本格式检查(Length + NameLen + Options + Status + StmtLength + Columns) */
    if (bytebuff_remaining(p_st_data) < 4 + 1 + 4 + 1 + 4 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURCLOSE的总长度Length */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_token_len
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC || u32_token_len < 1 + 4 + 1 + 4 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (u32_token_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto unknow;
    }

    /* 取得FRTDS_CURCLOSE的NameLen */
    bytebuff_get_char(p_st_data, &u8_name_len);
    /* a maximum length of FRTDS_MAX_NAME (30) is widely supported */
    if (u8_name_len > FRTDS_MAX_NAME
        || u32_token_len <= (unsigned int)(1 + u8_name_len + 4 + 1 + 4 + 2))
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* get cursor name */
    i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_cursor_name[u8_name_len] = '\0';
    /* 取得options */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_options
                            , p_st_session->i_lint4_endian);
    /*
    *  Cursor option values is 0x00000000,0x00000001,0x00000002，0x00000004,
    *  0x00000008,0x00000010,0x00000020，0x00000040,0x00000080,0x00000100
    */
    if (i_ret != FR_SUCC || u32_options & 0xFFFFFE00)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status & 0xFE)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u32_token_len -= 1 + u8_name_len + 4 + 1;

    /* 取得StmtLength */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_statement_len
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC || u32_token_len < 4 + u32_statement_len + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得statement */
    p_statement = (char *)frmalloc(u32_statement_len + 1);
    if (p_statement == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_statement, u32_statement_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_statement);
        return APM_L7_ANALYZE_FAIL;
    }
    p_statement[u32_statement_len] = '\0';
    u32_token_len -= 4 + u32_statement_len;

    /* 取得#Columns */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_columns
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        frfree(p_statement);
        return APM_L7_ANALYZE_FAIL;
    }
    u32_token_len -= 2;
    /* check #Columns */
    if (u16_columns)
    {
        frdbg("Plesase attention to this packet\n");
        while (u16_columns)
        {
            u16_columns--;
            if (u32_token_len == 0)
            {
                frfree(p_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_get_char(p_st_data, &u8_col_len);
            if (u32_token_len < (unsigned int)(1 + u8_col_len))
            {
                frfree(p_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            /* 跳过ColumnName */
            bytebuff_skip(p_st_data, u8_col_len);
            u32_token_len -= 1 + u8_col_len;
        }
    }

    /* 只剩下最后1字节的#Columns */
    if (u32_token_len)
    {
        frfree(p_statement);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置出力 */
    *p_i_status = u8_status;
    if (*pp_statement)
    {
        frdbg("Allrady get sql[%s] before\n", *pp_statement);
        /* 合并sql,实际情况应该不会发生 */
        i_ret = __sybase_merge_string(*pp_statement, p_statement, &p_statement_tmp);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frfree(p_statement);
            return APM_L7_ANALYZE_FAIL;
        }
        p_statement = p_statement_tmp;
    }
    *pp_statement = p_statement;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURDELETE TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_l_cursor_id(close的游标ID)
*           :  p_cursor_name(close的游标名称)
*           :  p_i_del_flg(是否需要删除游标标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curdelete_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , long *p_l_cursor_id
                               , char *p_cursor_name)
{
    /* 定义
    * 解析解析FRTDS_CURDELETE = 0x81
    *                         Length(2byte unsigned integer)
    *                         CursorId(4byte unsigned integer)
    *                         NameLength(1byte unsigned integer)
    *                         CursorName
    *                         Status(1byte)
    *                         TableLength(1byte unsigned integer)
    *                         TableName
    */
    int i_ret = FR_SUCC;
    //uint8_t u8_options = 0;
    uint8_t u8_name_len = 0;
    uint8_t u8_table_name_len = 0;
    uint16_t u16_token_len = 0;
    uint32_t u32_cursor_id = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1 + 1)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURDELETE的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURDELETE的CursorId */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_cursor_id
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* NameLength and CursorName are only included if CursorId is equal to 0 */
    if (u32_cursor_id == 0)
    {
        /* 取得FRTDS_CURDELETE的NameLength */
        bytebuff_get_char(p_st_data, &u8_name_len);
        /* NameLength must be > 0 and <= FRTDS_MAX_NAME(30) */
        if (u8_name_len == 0 || u8_name_len > FRTDS_MAX_NAME
            || u16_token_len <= u8_name_len + 4 + 1 + 1)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得FRTDS_CURDELETE的CursorName */
        i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_cursor_name[u8_name_len] = '\0';
        u16_token_len -= 4 + 1 + u8_name_len;
    }
    else
    {
        u16_token_len -= 4;
    }

    /* Status + TableLength */
    if (u16_token_len < 1 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得FRTDS_CURDELETE的Status */
    bytebuff_get_char(p_st_data, &u8_name_len);
    /* 跳过FRTDS_CURDELETE的TableNameLength */
    bytebuff_get_char(p_st_data, &u8_table_name_len);
    if (u16_token_len != 1 + 1 + u8_table_name_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_table_name_len);

    *p_l_cursor_id = u32_cursor_id;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURFETCH TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_l_cursor_id(close的游标ID)
*           :  p_cursor_name(close的游标名称)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curfetch_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , long *p_l_cursor_id
                               , char *p_cursor_name)
{
    /* 定义
    * 解析FRTDS_CURFETCH = 0x82
    *                    Length(2byte unsigned integer)
    *                    CursorId(4byte unsigned integer)
    *                    NameLength(1byte unsigned integer)
    *                    CursorName(NameLength)
    *                    Type(1byte)
    *                    Row#(4byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_type = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;
    uint32_t u32_cursor_id = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURFETCH的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURFETCH的CursorId */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_cursor_id
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 4;

    /* NameLength and CursorName are only included if CursorId is equal to 0 */
    if (u32_cursor_id == 0)
    {
        /* 取得FRTDS_CURFETCH的NameLength */
        bytebuff_get_char(p_st_data, &u8_name_len);
        /* NameLength must be > 0 and <= FRTDS_MAX_NAME(30) */
        if (u8_name_len == 0 || u8_name_len > FRTDS_MAX_NAME
            || u16_token_len < 1 + u8_name_len + 1)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得FRTDS_CURFETCH的CursorName */
        i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_cursor_name[u8_name_len] = '\0';
        u16_token_len -= 1 + u8_name_len;
    }

    /* 取得FRTDS_CURFETCH的Type */
    bytebuff_get_char(p_st_data, &u8_type);
    u16_token_len--;
    switch (u8_type)
    {
        case 1:
        case 2:
        case 3:
        case 4:
            if (u16_token_len)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            break;

        case 5:
        case 6:
            if (u16_token_len != 4)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_skip(p_st_data, 4);
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    *p_l_cursor_id = u32_cursor_id;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURINFO TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_l_cursor_id(close的游标ID)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curinfo_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , long *p_l_cursor_id
                               , char *p_cursor_name)
{
    /* 定义
    * 解析FRTDS_CURINFO = 0x83
    *                   Length(2byte unsigned integer)
    *                   CursorId(4byte unsigned integer)
    *                   NameLength(1byte unsigned integer)
    *                   CursorName(NameLength)
    *                   Command(1byte)
    *                   Stauts(2byte unsigned integer)
    *                   RowCount(4byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_command = 0;
    uint16_t u16_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;
    uint32_t u32_cursor_id = 0;

    /* 基本格式检查(Length + CursorId + Command + Stauts) */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURINFO的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURINFO的CursorId */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_cursor_id
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 4;

    /* NameLength and CursorName are only included if CursorId is equal to 0 */
    if (u32_cursor_id == 0)
    {
        /* 取得FRTDS_CURINFO的NameLength */
        bytebuff_get_char(p_st_data, &u8_name_len);
        /* NameLength must be > 0 and <= FRTDS_MAX_NAME(30) */
        if (u8_name_len == 0 || u8_name_len > FRTDS_MAX_NAME
            || u16_token_len < 1 + u8_name_len + 1 + 2)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* get FRTDS_CURINFO的CursorName */
        i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_cursor_name[u8_name_len] = '\0';
        u16_token_len -= 1 + u8_name_len;
    }

    /* 取得FRTDS_CURINFO的command */
    bytebuff_get_char(p_st_data, &u8_command);
    switch (u8_command)
    {
        case 1:
        case 2:
        case 3:
        case 4:
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /* 取得FRTDS_CURINFO的status */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_status
                              , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC || u16_status & 0x0080)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 1 + 2;

    /* status的FRTDS_CUR_ISTAT_ROWCNT为真时row count存在 */
    if (u16_status &0x0020)
    {
        if (u16_token_len != 4)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 跳过FRTDS_CURINFO的row count */
        bytebuff_skip(p_st_data, 4);
    }
    else if (u16_token_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    *p_l_cursor_id = u32_cursor_id;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURINFO2 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_l_cursor_id(close的游标ID)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curinfo2_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , long *p_l_cursor_id
                               , char *p_cursor_name)
{
    /* 定义
    * 解析FRTDS_CURINFO2 = 0x87
    *                   Length(2byte unsigned integer)
    *                   CursorId(4byte unsigned integer)
    *                   NameLength(1byte unsigned integer)
    *                   CursorName(NameLength)
    *                   Command(1byte)
    *                   Stauts(4byte unsigned integer)
    *                   RowCount(4byte unsigned integer)
    *                   RowNum(4byte unsigned integer)
    *                   TotalRows(4byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_command = 0;
    uint32_t u32_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;
    uint32_t u32_cursor_id = 0;

    /* 基本格式检查(Length + CursorId + Command + Stauts + RowNum + TotalRows) */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1 + 4 + 4 + 4)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURINFO2的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1 + 4 + 4 + 4)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURINFO2的CursorId */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_cursor_id
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 4;

    /* NameLength and CursorName are only included if CursorId is equal to 0 */
    if (u32_cursor_id == 0)
    {
        /* 取得FRTDS_CURINFO的NameLength */
        bytebuff_get_char(p_st_data, &u8_name_len);
        /* NameLength must be > 0 and <= FRTDS_MAX_NAME(30) */
        if (u8_name_len == 0 || u8_name_len > FRTDS_MAX_NAME
            || u16_token_len < 1 + u8_name_len + 1 + 4 + 4 + 4)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得FRTDS_CURINFO的CursorName */
        i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_cursor_name[u8_name_len] = '\0';
        u16_token_len -= 1 + u8_name_len;
    }

    /* 取得FRTDS_CURINFO2的command */
    bytebuff_get_char(p_st_data, &u8_command);
    switch (u8_command)
    {
        case 1:
        case 2:
        case 3:
        case 4:
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /* 取得FRTDS_CURINFO2的status */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_status
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC || u32_status & 0xFFFFE000)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 1 + 4;

    /*
    *  RowCount is always present in the stream since the FRTDS_CUR_ISTAT_ROWCNT
    *  status bit is always set for FRTDS_CURINFO2
    */
    if (u32_status & FRTDS_CUR_ISTAT_ROWCNT)
    {
        /* 跳过RowCount + RowNum + TotalRows */
        if (u16_token_len == 4 + 4 + 4)
        {
            bytebuff_skip(p_st_data, 12);
        }
        else
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        /* 跳过RowNum + TotalRows */
        if (u16_token_len == 4 + 4)
        {
            bytebuff_skip(p_st_data, 8);
        }
        else
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }

    *p_l_cursor_id = u32_cursor_id;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURINFO3 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_l_cursor_id(close的游标ID)
*           :  p_cursor_name(close的游标名称)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curinfo3_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , L7session_sybase *p_st_session
                                , long *p_l_cursor_id
                                , char *p_cursor_name)
{
    /* 定义
    * 解析FRTDS_CURINFO3 = 0x88
    *                   Length(2byte unsigned integer)
    *                   CursorId(4byte unsigned integer)
    *                   NameLength(1byte unsigned integer)
    *                   CursorName(NameLength)
    *                   Command(1byte)
    *                   Stauts(4byte unsigned integer)
    *                   RowNum(4byte unsigned integer)
    *                   TotalRows(4byte unsigned integer)
    *                   RowCount(4byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_command = 0;
    uint32_t u32_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;
    uint32_t u32_cursor_id = 0;

    /* 基本格式检查(Length + CursorId + Command + Stauts + RowNum + TotalRows) */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1 + 4 + 4 + 4)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURINFO3的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1 + 4 + 4 + 4)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURINFO3的CursorId */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_cursor_id
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 4;

    /* NameLength and CursorName are only included if CursorId is equal to 0 */
    if (u32_cursor_id == 0)
    {
        /* 取得FRTDS_CURINFO的NameLength */
        bytebuff_get_char(p_st_data, &u8_name_len);
        /* NameLength must be > 0 and <= FRTDS_MAX_NAME(30) */
        if (u8_name_len == 0 || u8_name_len > FRTDS_MAX_NAME
            || u16_token_len < 1 + u8_name_len + 1 + 4 + 4 + 4)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得FRTDS_CURINFO的CursorName */
        i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_cursor_name[u8_name_len] = '\0';
        u16_token_len -= 1 + u8_name_len;
    }

    /* 取得FRTDS_CURINFO3的command */
    bytebuff_get_char(p_st_data, &u8_command);
    switch (u8_command)
    {
        case 1:
        case 2:
        case 3:
        case 4:
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /* 取得FRTDS_CURINFO3的status */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_status
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC || u32_status & 0xFFFFE000)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 1 + 4;

    /*
    *  RowCount is always present in the stream since the FRTDS_CUR_ISTAT_ROWCNT
    *  status bit is always set for FRTDS_CURINFO3
    */
    if (u32_status & FRTDS_CUR_ISTAT_ROWCNT)
    {
        /* 跳过RowNum + TotalRows + RowCount */
        if (u16_token_len == 4 + 4 + 4)
        {
            bytebuff_skip(p_st_data, 12);
        }
        else
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        /* 跳过RowNum + TotalRows */
        if (u16_token_len == 4 + 4)
        {
            bytebuff_skip(p_st_data, 8);
        }
        else
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }

    *p_l_cursor_id = u32_cursor_id;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CUROPEN TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_l_cursor_id(游标ID)
*           :  p_cursor_name(游标名称)
*           :  p_i_status(status)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curopen_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , long *p_l_cursor_id
                               , char *p_cursor_name
                               , int *p_i_status)
{
    /* 定义
    * 解析FRTDS_CUROPEN = 0x84
    *                  Length(2byte unsigned integer)
    *                  CursorId(4byte unsigned integer)
    *                  NameLength(1byte unsigned integer)
    *                  CursorName(NameLength)
    *                  Status(1byte)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;
    uint32_t u32_cursor_id = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1)
    {
        goto unknow;
    }

    /* 取得FRTDS_CUROPEN的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_CUROPEN的CursorId */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_cursor_id
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 4;

    /* NameLength and CursorName are only included if CursorId is equal to 0 */
    if (u32_cursor_id == 0)
    {
        /* 取得FRTDS_CUROPEN的NameLength */
        bytebuff_get_char(p_st_data, &u8_name_len);
        /* NameLength must be > 0 and <= FRTDS_MAX_NAME(30) */
        if (u8_name_len == 0 || u8_name_len > FRTDS_MAX_NAME
            || u16_token_len != 1 + u8_name_len + 1)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得FRTDS_CUROPEN的CursorName */
        i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_cursor_name[u8_name_len] = '\0';
    }
    else if (u16_token_len != 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得FRTDS_CUROPEN的Status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status != 0 && u8_status != 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    *p_i_status = u8_status;
    *p_l_cursor_id = u32_cursor_id;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_CURUPDATE TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_l_cursor_id(游标ID)
*           :  p_cursor_name(游标名称)
*           :  pp_statement(sql statement)
*           :  p_i_status(status)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_cursor_name内存长度大于30
*******************************************************************************/
int sybase_parse_curupdate_token(Frbyte_Packet *p_st_data
                                 , int i_whole_flg
                                 , L7session_sybase *p_st_session
                                 , long *p_l_cursor_id
                                 , char *p_cursor_name
                                 , char **pp_statement
                                 , int *p_i_status)
{
    /* 定义
    * 解析FRTDS_CURUPDATE = 0x85
    *                     Length(2byte unsigned integer)
    *                     CursorId(4byte unsigned integer)
    *                     NameLength(1byte unsigned integer)
    *                     CursorName
    *                     Status(1byte)
    *                     TableLength(1byte unsigned integer)
    *                     TableName
    *                     StmtLength(2byte unsigned integer)
    *                     Statement
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_statement_len = 0;
    uint16_t u16_token_len = 0;
    uint32_t u32_cursor_id = 0;
    char *p_statement = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1 + 1 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURUPDATE的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1 + 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURUPDATE的CursorId */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_cursor_id
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 4;

    /* NameLength and CursorName are only included if CursorId is equal to 0 */
    if (u32_cursor_id == 0)
    {
        /* 取得FRTDS_CUROPEN的NameLength */
        bytebuff_get_char(p_st_data, &u8_name_len);
        /* NameLength must be > 0 and <= FRTDS_MAX_NAME(30) */
        if (u8_name_len == 0 || u8_name_len > FRTDS_MAX_NAME
            || u16_token_len != 1 + u8_name_len + 1 + 1 + 2)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得FRTDS_CUROPEN的CursorName */
        i_ret = bytebuff_get_bytes(p_st_data, p_cursor_name, u8_name_len);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_cursor_name[u8_name_len] = '\0';
        u16_token_len -= 1 + u8_name_len;
    }

    /* 取得FRTDS_CURUPDATE的Status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status & 0xFC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len--;

    /* 取得FRTDS_CURUPDATE的TableLength */
    bytebuff_get_char(p_st_data, &u8_name_len);
    if (u16_token_len < 1 + u8_name_len + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 跳过table name */
    bytebuff_skip(p_st_data, u8_name_len);
    u16_token_len -= 1 + u8_name_len;

    /* 取得FRTDS_CURUPDATE的TableLength */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_statement_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len != 2 + u16_statement_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得sql statement */
    p_statement = (char *)frmalloc(u16_statement_len + 1);
    if (p_statement == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    i_ret = bytebuff_get_bytes(p_st_data, p_statement, u16_statement_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_statement[u16_statement_len] = '\0';

    *p_i_status = u8_status;
    *p_l_cursor_id = u32_cursor_id;
    *pp_statement = p_statement;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_DBRPC TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  pp_rpc_name(RPC名称)
*           :  p_i_options(options)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_dbrpc_token(Frbyte_Packet *p_st_data
                             , int i_whole_flg
                             , L7session_sybase *p_st_session
                             , char **pp_rpc_name
                             , int *p_i_options)
{
    /* 定义
    * 解析FRTDS_DBRPC = 0xE6
    *                 Length(2byte unsigned integer)
    *                 NameLen(1byte unsigned integer)
    *                 RPCName
    *                 Options(2byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;
    uint16_t u16_options = 0;
    char *p_rpc_name = NULL;
    char *p_rpc_name_tmp = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 1 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURUPDATE的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                               , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得RPC Name长度 */
    bytebuff_get_char(p_st_data, &u8_name_len);
    if (u16_token_len != 1 + u8_name_len + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得RPC Name */
    p_rpc_name = (char *)frmalloc(u8_name_len + 1);
    if (p_rpc_name == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_rpc_name, u8_name_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_rpc_name);
        return APM_L7_ANALYZE_FAIL;
    }
    p_rpc_name[u8_name_len] = '\0';

    /* 取得options */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_options
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_options & 0xFC)
    {
        frfree(p_rpc_name);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 出力设置 */
    *p_i_options = u16_options;
    if (*pp_rpc_name)
    {
        frdbg("Allrady get sql[%s] before\n", *pp_rpc_name);
        i_ret = __sybase_merge_string(*pp_rpc_name, p_rpc_name, &p_rpc_name_tmp);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frfree(p_rpc_name);
            return APM_L7_ANALYZE_FAIL;
        }
        p_rpc_name = p_rpc_name_tmp;
    }
    *pp_rpc_name = p_rpc_name;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_DBRPC2 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  pp_rpc_name(RPC名称)
*           :  p_i_options(options)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_dbrpc2_token(Frbyte_Packet *p_st_data
                             , int i_whole_flg
                             , L7session_sybase *p_st_session
                             , char **pp_rpc_name
                             , int *p_i_options)
{
    /* 定义
    * 解析FRTDS_DBRPC2 = 0xE8
    *                 Length(2byte unsigned integer)
    *                 NameLen(2byte unsigned integer)
    *                 RPCName
    *                 Options(2byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint16_t u16_name_len = 0;
    uint16_t u16_token_len = 0;
    uint16_t u16_options = 0;
    char *p_rpc_name = NULL;
    char *p_rpc_name_tmp = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 2 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_CURUPDATE的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 2 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得RPC Name长度 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_name_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len != 2 + u16_name_len + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得RPC Name */
    p_rpc_name = (char *)frmalloc(u16_name_len + 1);
    if (p_rpc_name == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_rpc_name, u16_name_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_rpc_name);
        return APM_L7_ANALYZE_FAIL;
    }
    p_rpc_name[u16_name_len] = '\0';

    /* 取得options */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_options
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_options & 0xFC)
    {
        frfree(p_rpc_name);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置出力 */
    *p_i_options = u16_options;
    if (*pp_rpc_name)
    {
        frdbg("Allrady get sql[%s] before\n", *pp_rpc_name);
        i_ret = __sybase_merge_string(*pp_rpc_name, p_rpc_name, &p_rpc_name_tmp);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frfree(p_rpc_name);
            return APM_L7_ANALYZE_FAIL;
        }
        p_rpc_name = p_rpc_name_tmp;
    }
    *pp_rpc_name = p_rpc_name;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_DONE TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_i_err_flg(错误flag)
*           :  p_ul_effect_rows(影响行数)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_done_token(Frbyte_Packet *p_st_data
                            , int i_whole_flg
                            , L7session_sybase *p_st_session
                            , int *p_i_err_flg
                            , unsigned long *p_ul_effect_rows)
{
    /* 定义
    * 解析FRTDS_DONE = 0xFD
    *                Status(2byte unsigned integer)
    *                TranState(2byte unsigned integer)
    *                Count(4byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint16_t u16_status = 0;
    uint16_t u16_state = 0;
    uint32_t u32_rows = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 2 + 4)
    {
        goto unknow;
    }

    /* 取得FRTDS_DONE的Status */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_status
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_status & 0xFF80)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置error flag */
    if (FRTDS_DONE_ERROR & u16_status)
    {
        *p_i_err_flg = FR_YES;
    }
    else
    {
        *p_i_err_flg = FR_NO;
    }

    /* 取得FRTDS_DONE的TranState */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_state
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    switch(u16_state)
    {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /*
    *  If the FRTDS_DONE_COUNT bit in the Status field is set,
    *  then the count is meaningful and it gives the number of
    *  rows that were affected by the current command. */
    if (FRTDS_DONE_COUNT & u16_status)
    {
        /* 取得FRTDS_DONE的effect rows */
        i_ret = bytebuff_get_int(p_st_data, 4, &u32_rows
                                , p_st_session->i_lint4_endian);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        *p_ul_effect_rows += u32_rows;
    }
    else
    {
        bytebuff_skip(p_st_data, 4);
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_DONEPROC_DONEINPROC TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_i_err_flg(错误flag)
*           :  p_ul_effect_rows(影响行数)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_doneproc_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , L7session_sybase *p_st_session
                                , int *p_i_err_flg
                                , unsigned long *p_ul_effect_rows)
{
    /* 定义
    * 解析FRTDS_DONE = 0xFE/0xFF
    *                Status(2byte unsigned integer)
    *                TranState(2byte unsigned integer)
    *                Count(4byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint16_t u16_status = 0;
    uint16_t u16_state = 0;
    uint32_t u32_rows = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 2 + 4)
    {
        goto unknow;
    }

    /* 取得FRTDS_DONE的Status */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_status
                              , p_st_session->i_lint2_endian);
    //if (i_ret != FR_SUCC || u16_status & 0xFFC8) todo 与协议不一致
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置error flag */
    if (FRTDS_DONE_ERROR & u16_status)
    {
        *p_i_err_flg = FR_YES;
    }
    else
    {
        *p_i_err_flg = FR_NO;
    }

    /* 取得FRTDS_DONE的TranState */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_state
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    switch(u16_state)
    {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /*
    *  If the FRTDS_DONE_COUNT bit in the Status field is set,
    *  then the count is meaningful and it gives the number of
    *  rows that were affected by the current command. */
    if (FRTDS_DONE_COUNT & u16_status)
    {
        /* 取得FRTDS_DONE的effect rows */
        i_ret = bytebuff_get_int(p_st_data, 4, &u32_rows
                                , p_st_session->i_lint4_endian);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        *p_ul_effect_rows += u32_rows;
    }
    else
    {
        bytebuff_skip(p_st_data, 4);
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_DYNAMIC TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  i_req_resp(resquest or response)
*           :  p_i_type(type)
*           :  p_id(ID)
*           :  pp_statement(Sql statement)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_id内存长度大于30
*******************************************************************************/
int sybase_parse_dynamic_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , int i_req_resp
                               , int *p_i_type
                               , int *p_i_status
                               , char *p_id
                               , char **pp_statement)
{
    /* 定义
    * 解析FRTDS_DYNAMIC = 0xE7
    *                   Length(2byte unsigned integer)
    *                   Type(1byte unsigned integer)
    *                   Status(1byte unsigned integer)
    *                   IdLen(1byte unsigned integer)
    *                   ID
    *                   StmtLen(2byte unsigned integer)
    *                   Stmt
    */
    int i_ret = FR_SUCC;
    uint8_t u8_type = 0;
    uint8_t u8_status = 0;
    uint8_t u8_id_len = 0;
    uint16_t u16_token_len = 0;
    uint16_t u16_stmt_len = 0;
    char *p_statement = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 1 + 1 + 1)
    {
        goto unknow;
    }

    /* 取得FRTDS_DYNAMIC的Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 1 + 1 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_DYNAMIC的type */
    bytebuff_get_char(p_st_data, &u8_type);

    /* 取得FRTDS_DYNAMIC的status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status & 0xFC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 1 + 1;

    /* 取得FRTDS_DYNAMIC的IdLen */
    /* In practice, a maximum length of 30 is widely supported. */
    bytebuff_get_char(p_st_data, &u8_id_len);
    if (u8_id_len > 30 || u16_token_len < 1 + u8_id_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得ID */
    i_ret = bytebuff_get_bytes(p_st_data, p_id, u8_id_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_id[u8_id_len] = '\0';
    u16_token_len -= 1 + u8_id_len;

    /*
    *  The Stmt argument is only used in the FRTDS_DYN_PREPARE
    *  and FRTDS_DYN_EXEC_IMMED data streams.
    */
    //TODO实际于协议不大一致
    //if (u8_type & FRTDS_DYN_PREPARE || u8_type & FRTDS_DYN_EXEC_IMMED)
    if (u16_token_len >= 2)
    {
        //if (u16_token_len < 2)
        //{
        //    return APM_L7_ANALYZE_FAIL;
        //}

        /* 取得FRTDS_DYNAMIC的StntLen */
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_stmt_len
                                  , p_st_session->i_lint2_endian);
        if (i_ret != FR_SUCC || u16_token_len != 2 + u16_stmt_len)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* 取得statement */
        if (u16_stmt_len && i_req_resp == FR_CLIENT_IP_PORT)//只有客户端才去取sql,服务端也不会发
        {
            p_statement = (char *)frmalloc(u16_stmt_len + 1);
            if (p_statement == NULL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = bytebuff_get_bytes(p_st_data, p_statement, u16_stmt_len);
            if (i_ret != FR_SUCC)
            {
                frfree(p_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            p_statement[u16_stmt_len] = '\0';
            *pp_statement = p_statement;
        }
        else
        {
            /* skip sql */
            bytebuff_skip(p_st_data, u16_stmt_len);
        }
    }
    else if (u16_token_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置出力 */
    *p_i_type = u8_type;
    *p_i_status = u8_status;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_DYNAMIC2 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_i_type(type)
*           :  p_id(ID)
*           :  pp_statement(Sql statement)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_id内存长度大于30
*******************************************************************************/
int sybase_parse_dynamic2_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , int i_req_resp
                               , int *p_i_type
                               , int *p_i_status
                               , char *p_id
                               , char **pp_statement)
{
    /* 定义
    * 解析FRTDS_DYNAMIC = 0xE7
    *                   Length(4byte unsigned integer)
    *                   Type(1byte unsigned integer)
    *                   Status(1byte unsigned integer)
    *                   IdLen(1byte unsigned integer)
    *                   ID
    *                   StmtLen(4byte unsigned integer)
    *                   Stmt
    */
    int i_ret = FR_SUCC;
    uint8_t u8_type = 0;
    uint8_t u8_status = 0;
    uint8_t u8_id_len = 0;
    uint32_t u32_token_len = 0;
    uint32_t u32_stmt_len = 0;
    char *p_statement = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 4 + 1 + 1 + 1)
    {
        goto unknow;
    }

    /* 取得FRTDS_DYNAMIC的Length */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_token_len
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC || u32_token_len < 1 + 1 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (u32_token_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto unknow;
    }

    /* 取得FRTDS_DYNAMIC的type */
    bytebuff_get_char(p_st_data, &u8_type);

    /* 取得FRTDS_DYNAMIC的status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status & 0xFC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u32_token_len -= 1 + 1;

    /* 取得FRTDS_DYNAMIC的IdLen */
    /* In practice, a maximum length of 30 is widely supported. */
    bytebuff_get_char(p_st_data, &u8_id_len);
    if (u8_id_len > 30 || u32_token_len < (unsigned int)(1 + u8_id_len))
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得ID */
    i_ret = bytebuff_get_bytes(p_st_data, p_id, u8_id_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_id[u8_id_len] = '\0';
    u32_token_len -= 1 + u8_id_len;

    /*
    *  The Stmt argument is only used in the FRTDS_DYN_PREPARE
    *  and FRTDS_DYN_EXEC_IMMED data streams.
    */
    //TODO 实际与协议不符合
    //if (u8_type & FRTDS_DYN_PREPARE || u8_type & FRTDS_DYN_EXEC_IMMED)
    if (u32_token_len >= 4)
    {
        //if (u32_token_len < 4)
        //{
        //    return APM_L7_ANALYZE_FAIL;
        //}

        /* 取得FRTDS_DYNAMIC的StntLen */
        i_ret = bytebuff_get_int(p_st_data, 4, &u32_stmt_len
                                , p_st_session->i_lint4_endian);
        if (i_ret != FR_SUCC || u32_token_len != 4 + u32_stmt_len)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* 取得statement */
        if (u32_stmt_len && i_req_resp == FR_CLIENT_IP_PORT)//只有客户端才去取sql,服务端也不会发
        {
            /* 取得statement */
            p_statement = (char *)frmalloc(u32_stmt_len + 1);
            if (p_statement == NULL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = bytebuff_get_bytes(p_st_data, p_statement, u32_stmt_len);
            if (i_ret != FR_SUCC)
            {
                frfree(p_statement);
                return APM_L7_ANALYZE_FAIL;
            }
            p_statement[u32_stmt_len] = '\0';
            *pp_statement = p_statement;
        }
        else
        {
            bytebuff_skip(p_st_data, u32_stmt_len);
        }
    }
    else if (u32_token_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    *p_i_status = u8_status;
    *p_i_type = u8_type;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_EED TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_ui_msg_num(message number)
*           :  pp_msg_info(message information)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_eed_token(Frbyte_Packet *p_st_data
                           , int i_whole_flg
                           , L7session_sybase *p_st_session
                           , int *p_i_msg_num
                           , char **pp_msg_info)
{
    /* 定义
    * 解析FRTDS_EED = 0xE5
    *               Length(2byte unsigned integer)
    *               MsgNumber(4byte unsigned integer)
    *               State(1byte unsigned integer)
    *               Class(1byte unsigned integer)
    *               SQLStateLen(1byte unsigned integer)
    *               SQLState
    *               Status(1byte unsigned integer)
    *               TranState(2byte unsigned integer)
    *               MsgLength(2byte unsigned integer)
    *               Msg
    *               ServerLength(1byte unsigned integer)
    *               ServerName
    *               ProlLen(1byte unsigned integer)
    *               ProcName
    *               LineNum(2byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_ser_len = 0;
    uint8_t u8_proc_len = 0;
    uint8_t u8_status = 0;
    uint8_t u8_state_len = 0;
    uint16_t u16_token_len = 0;
    uint16_t u16_state = 0;
    //uint16_t u16_stmt_len = 0;
    uint32_t u32_msg_num = 0;
    uint16_t u16_msg_len = 0;
    char *p_msg_info = NULL;
    char *p_msg_info_tmp = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 4 * 1 + 2 + 2 + 1 + 1 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_EED的Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 4 * 1 + 2 + 2 + 1 + 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_EED的MsgNumber */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_msg_num
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 4;

    /* 跳过State + Class */
    bytebuff_skip(p_st_data, 1 + 1);
    u16_token_len -= 1 + 1;
    /* 跳过SQLState */
    bytebuff_get_char(p_st_data, &u8_state_len);
    if (u16_token_len < 1 + u8_state_len + 1 + 2 + 2 + 1 + 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_state_len);
    u16_token_len -= 1 + u8_state_len;

    /* Check status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status & 0xFC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len--;

    /* Check TranState */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_state
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 2;

    /* 取得message信息 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_msg_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 2 + u16_msg_len + 1 + 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_msg_info = (char *)frmalloc(u16_msg_len + 1);
    if (p_msg_info == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_msg_info, u16_msg_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_msg_info[u16_msg_len] = '\0';
    u16_token_len -= 2 + u16_msg_len;

    /* 跳过ServerName */
    bytebuff_get_char(p_st_data, &u8_ser_len);
    if (u16_token_len < 1 + u8_ser_len + 1 + 2)
    {
        frfree(p_msg_info);
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_ser_len);
    u16_token_len -= 1 + u8_ser_len;

    /* 跳过ProcName和LineNumber*/
    bytebuff_get_char(p_st_data, &u8_proc_len);
    if (u16_token_len != 1 + u8_proc_len + 2)
    {
        frfree(p_msg_info);
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_proc_len + 2);

    *p_i_msg_num = (int)u32_msg_num;
    if (*pp_msg_info)
    {
        frdbg("Allrady get sql[%s] before\n", *pp_msg_info);
        i_ret = __sybase_merge_string(*pp_msg_info, p_msg_info, &p_msg_info_tmp);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_msg_info = p_msg_info_tmp;
    }
    *pp_msg_info = p_msg_info;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ENVCHANGE TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  pp_charset(charset)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_envchange_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_ENVCHANGE = 0xE3
    *                     Length(2byte unsigned integer)
    *                     Type(1byte unsigned integer)
    *                     NewValLen(1byte unsigned integer)
    *                     NewValue
    *                     OldValLen(1byte unsigned integer)
    *                     OldValue
    */
    int i_ret = FR_SUCC;
    uint8_t u8_type = 0;
    uint8_t u8_old_len = 0;
    uint8_t u8_new_len = 0;
    uint16_t u16_token_len = 0;
    int i_chg_charset = FR_NO;
    int i_chg_db = FR_NO;
    char *p_charset = NULL;
    char *p_db_name = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_EED的Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析 */
    while(u16_token_len)
    {
        if (u16_token_len < 1 + 1 + 1)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得type */
        bytebuff_get_char(p_st_data, &u8_type);
        u16_token_len--;
        switch(u8_type)
        {
            /* 跳过 */
            case 2: //Language
            case 4: //packet size
                /* 取得newvalue长度 */
                bytebuff_get_char(p_st_data, &u8_new_len);
                if (u16_token_len < 1 + u8_new_len + 1)
                {
                    sybase_free(&p_charset);
                    sybase_free(&p_db_name);
                    return APM_L7_ANALYZE_FAIL;
                }
                bytebuff_skip(p_st_data, u8_new_len);
                u16_token_len -= 1 + u8_new_len;
                break;

            /* 取得DB */
            case 1: //DB
                /* 取得newvalue长度 */
                i_chg_db = FR_YES;
                bytebuff_get_char(p_st_data, &u8_new_len);
                if (u16_token_len < 1 + u8_new_len + 1)
                {
                    sybase_free(&p_charset);
                    sybase_free(&p_db_name);
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 取得charset */
                sybase_free(&p_db_name);
                p_db_name = (char *)frmalloc(u8_new_len + 1);
                if (p_db_name == NULL)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                i_ret = bytebuff_get_bytes(p_st_data, p_db_name, u8_new_len);
                if (i_ret != FR_SUCC)
                {
                    frfree(p_db_name);
                    sybase_free(&p_charset);
                    return APM_L7_ANALYZE_FAIL;
                }
                p_db_name[u8_new_len] = '\0';
                u16_token_len -= 1 + u8_new_len;
                break;

            /* 取得charset */
            case 3: //charset
                i_chg_charset = FR_YES;
                /* 取得newvalue长度 */
                bytebuff_get_char(p_st_data, &u8_new_len);
                if (u16_token_len < 1 + u8_new_len + 1)
                {
                    sybase_free(&p_charset);
                    sybase_free(&p_db_name);
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 取得charset */
                sybase_free(&p_charset);
                p_charset = (char *)frmalloc(u8_new_len + 1);
                if (p_charset == NULL)
                {
                    sybase_free(&p_db_name);
                    return APM_L7_ANALYZE_FAIL;
                }
                i_ret = bytebuff_get_bytes(p_st_data, p_charset, u8_new_len);
                if (i_ret != FR_SUCC)
                {
                    frfree(p_charset);
                    sybase_free(&p_db_name);
                    return APM_L7_ANALYZE_FAIL;
                }
                p_charset[u8_new_len] = '\0';
                u16_token_len -= 1 + u8_new_len;
                break;

            default:
                sybase_free(&p_charset);
                sybase_free(&p_db_name);
                return APM_L7_ANALYZE_FAIL;
        }

        /* 跳过oldvalue */
        bytebuff_get_char(p_st_data, &u8_old_len);
        if (u16_token_len < 1 + u8_old_len)
        {
            sybase_free(&p_charset);
            sybase_free(&p_db_name);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_old_len);
        u16_token_len -= 1 + u8_old_len;
    }

    /* 设置DB */
    if (i_chg_db == FR_YES)
    {
        sybase_free(&p_st_session->p_db_name);
        p_st_session->p_db_name = p_db_name;
    }
    /* 设置charset */
    if (i_chg_charset == FR_YES)
    {
        sybase_free(&p_st_session->p_tds_charset);
        p_st_session->p_tds_charset = p_charset;
    }
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ERROR TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_ui_error_num(error msessage number)
*           :  pp_error_msg(error msessage)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_error_token(Frbyte_Packet *p_st_data
                            , int i_whole_flg
                            , L7session_sybase *p_st_session
                            , int *p_i_error_num
                            , char **pp_error_msg)
{
    /* 定义
    * 解析FRTDS_ERROR = 0xAA
    *                 Length(2byte unsigned integer)
    *                 ErrorNumber(4byte unsigned integer)
    *                 State(1byte unsigned integer)
    *                 Class(1byte unsigned integer)
    *                 MsgLength(2byte unsigned integer)
    *                 ErrorMsg
    *                 ServerLength(1byte unsigned integer)
    *                 ServerName
    *                 ProcLen(1byte unsigned integer)
    *                 ProcName
    *                 LineNum(2byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_ser_len = 0;
    uint8_t u8_proc_len = 0;
    //uint8_t u8_status = 0;
    //uint8_t u8_state_len = 0;
    uint16_t u16_token_len = 0;
    //uint16_t u16_state = 0;
    //uint16_t u16_stmt_len = 0;
    uint32_t u32_error_num = 0;
    uint16_t u16_msg_len = 0;
    char *p_error_msg = NULL;
    char *p_error_msg_tmp = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1 + 1 + 2 + 1 + 1 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_ERROR的Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1 + 1 + 2 + 1 + 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_ERROR的ErrorNumber */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_error_num
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 4;

    /* 跳过State + Class */
    bytebuff_skip(p_st_data, 1 + 1);
    u16_token_len -= 1 + 1;
    /* 取得error message */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_msg_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 2 + u16_msg_len + 1 + 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_error_msg = (char *)frmalloc(u16_msg_len + 1);
    if (p_error_msg == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_error_msg, u16_msg_len);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_error_msg[u16_msg_len] = '\0';
    u16_token_len -= 2 + u16_msg_len;

    /* 跳过ServerName */
    bytebuff_get_char(p_st_data, &u8_ser_len);
    if (u16_token_len < 1 + u8_ser_len + 1 + 2)
    {
        frfree(p_error_msg);
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_ser_len);
    u16_token_len -= 1 + u8_ser_len;

    /* 跳过ProcName和LineNumber*/
    bytebuff_get_char(p_st_data, &u8_proc_len);
    if (u16_token_len != 1 + u8_proc_len + 2)
    {
        frfree(p_error_msg);
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_proc_len + 2);

    *p_i_error_num =(int)u32_error_num;
    if (*pp_error_msg)
    {
        frdbg("Allrady get sql[%s] before\n", *pp_error_msg);
        i_ret = __sybase_merge_string(*pp_error_msg, p_error_msg, &p_error_msg_tmp);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_error_msg =p_error_msg_tmp;
    }
    *pp_error_msg = p_error_msg;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_EVENTNOTICE TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_eventnotice_token(Frbyte_Packet *p_st_data
                                   , int i_whole_flg
                                   , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_EVENTNOTICE = 0xA2
    *                       Length(2byte unsigned integer)
    *                       NameLength(1byte unsigned integer)
    *                       EventName
    */
    int i_ret = FR_SUCC;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 1)
    {
        goto unknow;
    }

    /* 取得FRTDS_EVENTNOTICE的Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }
    /* 取得bytebuff_get_short */
    bytebuff_get_char(p_st_data, &u8_name_len);
    if (u16_token_len != 1 + u8_name_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_name_len);

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_INFO TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_info_token(Frbyte_Packet *p_st_data
                            , int i_whole_flg
                            , L7session_sybase *p_st_session
                            , int *p_i_error_num
                            , char **pp_error_msg)
{
    /* 定义
    * 解析FRTDS_INFO = 0xAB
    *                Length(2byte unsigned integer)
    *                InfoNumber(4byte unsigned integer)
    *                State(1byte unsigned integer)
    *                Class(1byte unsigned integer)
    *                MsgLength(2byte unsigned integer)
    *                InfoMsg
    *                ServerLength(1byte unsigned integer)
    *                ServerName
    *                ProcLen(1byte unsigned integer)
    *                ProcName
    *                LineNum(2byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_ser_len = 0;
    uint8_t u8_proc_len = 0;
    uint16_t u16_msg_len = 0;
    uint16_t u16_token_len = 0;
    uint32_t u32_msg_num = 0;
    char *p_error_msg = NULL;
    char *p_error_msg_tmp = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 4 + 1 + 1 + 2 + 1 + 1 + 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_INFO 的Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 4 + 1 + 1 + 2 + 1 + 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得FRTDS_INFO的InfoNumber */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_msg_num
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 跳过FRTDS_INFO的State + Class */
    bytebuff_skip(p_st_data, 1 + 1);
    u16_token_len -= 4 + 1 + 1;

    /* 取得info message */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_msg_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 2 + u16_msg_len + 1 + 1 + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_error_msg = (char *)frmalloc(u16_msg_len + 1);
    if (p_error_msg == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_error_msg, u16_msg_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_error_msg);
        return APM_L7_ANALYZE_FAIL;
    }
    p_error_msg[u16_msg_len] = '\0';
    u16_token_len -= 2 + u16_msg_len;

    /* 跳过ServerName */
    bytebuff_get_char(p_st_data, &u8_ser_len);
    if (u16_token_len < 1 + u8_ser_len + 1 + 2)
    {
        frfree(p_error_msg);
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_ser_len);
    u16_token_len -= 1 + u8_ser_len;

    /* 跳过ProcName和LineNumber*/
    bytebuff_get_char(p_st_data, &u8_proc_len);
    if (u16_token_len != 1 + u8_proc_len + 2)
    {
        frfree(p_error_msg);
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_proc_len + 2);

    *p_i_error_num = (int)u32_msg_num;
    if (*pp_error_msg)
    {
        frdbg("Allrady get sql[%s] before\n", *pp_error_msg);
        i_ret = __sybase_merge_string(*pp_error_msg, p_error_msg, &p_error_msg_tmp);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_error_msg = p_error_msg_tmp;
    }
    *pp_error_msg = p_error_msg;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_KEY TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_key_token(Frbyte_Packet *p_st_data
                          , int i_whole_flg
                          , L7session_sybase *p_st_session
                          , Frlist_header *p_lst_metadata)
{
    /* 定义
    * 解析FRTDS_KEY = 0xCA
    *               Length(0, 1, or 4 bytes)
    *               Paramter
    */
    int i_ret = FR_SUCC;
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    /* 根据id取得对应的ALTFMT */
    p_st_node = FRLIST_FIRST_NODE(p_lst_metadata);
    while (p_st_node)
    {
        p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
        /* skip keys */
        i_ret = __sybase_skip_data(p_st_data, i_whole_flg
                                  , p_st_session, p_st_metadata);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("Call __sybase_skip_data failed\n");
            return i_ret;
        }
        /* 取得下一个DataType */
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_LANGUAGE TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_i_status(status)
*           :  pp_sql(sql文)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_language_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , int *p_i_status
                               , char **pp_sql)
{
    /* 定义
    * 解析FRTDS_LANGUAGE = 0x21
    *                    Length(4byte unsigned integer)
    *                    Status(1byte unsigned integer)
    *                    Language
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    uint32_t u32_token_len = 0;
    char *p_sql = NULL;
    char *p_sql_tmp = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 4 + 1)
    {
        goto unknow;
    }
    /* 取得FRTDS_LANGUAGE的Length */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_token_len
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC || u32_token_len < 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (u32_token_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto unknow;
    }

    /* 取得status */
    bytebuff_get_char(p_st_data, &u8_status);
    u32_token_len--;
    /* 取得language */
    p_sql = (char *)frmalloc(u32_token_len + 1);
    if (p_sql == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_sql, u32_token_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_sql);
        return APM_L7_ANALYZE_FAIL;
    }
    p_sql[u32_token_len] = '\0';

    /* 设置出力 */
    if (*pp_sql)
    {
        frdbg("Allrady get sql[%s] before\n", *pp_sql);
        i_ret = __sybase_merge_string(*pp_sql, p_sql, &p_sql_tmp);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        p_sql = p_sql_tmp;
    }
    *pp_sql = p_sql;
    *p_i_status = u8_status;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_LOGINACK TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_i_status(status)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_loginack_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , int *p_i_status)
{
    /* 定义
    * 解析FRTDS_LOGINACK = 0xAD
    *                    Length(2byte unsigned integer)
    *                    Status(1byte unsigned integer)
    *                    TDSVersion(4byte unsigned integer)
    *                    NameLength(1byte unsigned integer)
    *                    ProgramName
    *                    ProgramVersion(4byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;
    //char *p_error_msg = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 1 + 4 + 1 + 4)
    {
        goto unknow;
    }
    /* 取得FRTDS_LANGUAGE的Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                               , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_token_len < 1 + 4 + 1 + 4)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* 取得status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status != 5 && u8_status != 6 && u8_status != 7)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 跳过TDSversion */
    bytebuff_skip(p_st_data, 4);
    u16_token_len -= 1 + 4;
    /* 跳过program name + ProgramVersion */
    bytebuff_get_char(p_st_data, &u8_name_len);
    if (u16_token_len != 1 + u8_name_len + 4)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, u8_name_len + 4);

    *p_i_status = u8_status;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_LOGOUT TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_logout_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg)
{
    /* 定义
    * 解析FRTDS_LOGOUT = 0x71
    *                  Options(1byte unsigned integer)
    */
    //int i_ret = FR_SUCC;
    uint8_t u8_options = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        goto unknow;
    }
    /* 取得Options */
    bytebuff_get_char(p_st_data, &u8_options);
    /* Options argument must be 0x00 */
    if (u8_options != 0x00)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_MSG TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_msg_token(Frbyte_Packet *p_st_data
                          , int i_whole_flg
                          , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_MSG = 0x65
    *               Length(1byte unsigned integer)
    *               Status(1byte unsigned integer)
    *               MsgId(2byte unsigned integer)
    *               FRTDS_PARAMFMT
    *               FRTDS_PARAMS
    */
    int i_ret = FR_SUCC;
    uint8_t u8_token_len = 0;
    uint8_t u8_status = 0;
    unsigned int ui_start_pos = 0;
    Frlist_header st_metadata;
    memset(&st_metadata, 0x0, sizeof(st_metadata));

    /* 基本格式检查Length+Status+MsgId */
    if (bytebuff_remaining(p_st_data) < 1 + 1 + 2)
    {
        goto unknow;
    }
    /* 取得Length */
    bytebuff_get_char(p_st_data, &u8_token_len);
    if (bytebuff_remaining(p_st_data) < u8_token_len)
    {
        goto unknow;
    }
    /* 取得Status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status != 0 && u8_status != 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* skip MsgId */
    bytebuff_skip(p_st_data, 2);
    u8_token_len -= 1 + 2;
    /* 无params */
    if (u8_status == 0)
    {
        if (u8_token_len)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        ui_start_pos = bytebuff_remaining(p_st_data);
        i_ret = sybase_parse_paramfmt_token(p_st_data, i_whole_flg
                                           , p_st_session, &st_metadata);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }

        i_ret = sybase_parse_params_token(p_st_data, i_whole_flg, p_st_session
                                         , &st_metadata, 0, NULL);
        frlist_remove_all(&st_metadata, frdb_metadata_node_free);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
        else if (bytebuff_remaining(p_st_data) - ui_start_pos != u8_token_len)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_OFFSET TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_offset_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_OFFSET = 0x78
    *                  Keyword(2byte unsigned integer)
    *                  Offset(2byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint16_t u16_keyword = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 2)
    {
        goto unknow;
    }
    /* 取得Keyword */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_keyword
                              , p_st_session->i_lint2_endian);
    /* Options argument must be 0x00 */
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    switch (u16_keyword)
    {
        case FRTDS_OFF_SELECT:
        case FRTDS_OFF_FROM:
        case FRTDS_OFF_ORDER:
        case FRTDS_OFF_COMPUTE:
        case FRTDS_OFF_TABLE:
        case FRTDS_OFF_PROC:
        case FRTDS_OFF_STMT:
        case FRTDS_OFF_PARAM:
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /* 跳过Offset */
    bytebuff_skip(p_st_data, 2);
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_OPTIONCMD TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session 信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_optioncmd_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_OPTIONCMD = 0x78
    *                     Length(2byte unsigned integer)
    *                     Command(1byte unsigned integer)
    *                     Option(1byte unsigned integer)
    *                     ArgLength(1byte unsigned integer)
    *                     Option arg
    */
    int i_ret = FR_SUCC;
    uint16_t u16_token_len = 0;
    uint8_t u8_command = 0;
    uint8_t u8_option = 0;
    uint8_t u8_arg_len = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 1 + 1 + 1)
    {
        goto unknow;
    }
    /* 取得Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }
    /* 取得Command */
    bytebuff_get_char(p_st_data, &u8_command);
    switch(u8_command)
    {
        case 1:
        case 2:
        case 3:
        case 4:
            break;
        default:
            return APM_L7_ANALYZE_FAIL;
    }
    /* 取得Option */
    bytebuff_get_char(p_st_data, &u8_option);
    if (u8_option > 48)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得ArgLength */
    bytebuff_get_char(p_st_data, &u8_arg_len);
    u16_token_len -= 3;
    if (u8_arg_len != u16_token_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 跳过Option arg */
    bytebuff_skip(p_st_data, u8_arg_len);

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ORDERBY TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session 信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_orderby_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_ORDERBY = 0xA9
    *                   #Columns(2byte unsigned integer)
    *                   Column#(1byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint16_t u16_columns = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        goto unknow;
    }
    /* 取得Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_columns
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_columns)
    {
        goto unknow;
    }
    /* skip columns */
    bytebuff_skip(p_st_data, u16_columns);

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ORDERBY2 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_orderby2_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_ORDERBY = 0x22
    *                   #Length(4byte unsigned integer)
    *                   #Columns(2byte unsigned integer)
    *                   Column#(2byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint32_t u32_token_len = 0;
    uint16_t u16_columns = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 4 + 2)
    {
        goto unknow;
    }
    /* 取得Length */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_token_len
                             , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (u32_token_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto unknow;
    }
    /* 取得Columns */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_columns
                             , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (u32_token_len - 2 != u16_columns * 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* skip columns */
    bytebuff_skip(p_st_data, u32_token_len - 2);

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_PARAMFMT TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_lst_metadata(metadata list)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data和p_lst_metadata必须不为NULL
*******************************************************************************/
int sybase_parse_paramfmt_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , L7session_sybase *p_st_session
                                , Frlist_header *p_lst_metadata)
{
    /* 定义
    * 解析FRTDS_PARAMFMT = 0xEC
    *                    Length(2byte unsigned integer)
    *                    #Params(2byte unsigned integer)
    *                    NameLength(1byte unsigned integer)
    *                    ParamName
    *                    Status(1byte unsigned integer)
    *                    UserType(4byte unsigned integer)
    *                    DataType(1byte unsigned integer)
    *                    Length(1byte unsigned integer)
    *                    Precision(1byte unsigned integer)
    *                    Scale(1byte unsigned integer)
    *                    LocaleLen(1byte unsigned integer)
    *                    LocaleInfo
    *                    ClassLen(2byte unsigned integer)
    *                    ClassID(1byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_params = 0;
    uint16_t u16_token_len = 0;
    uint8_t u8_local_len = 0;
    int i_data_type = 0;
    unsigned int ui_len = 0;
    unsigned int ui_scale = 0;
    unsigned int ui_precision = 0;
    unsigned int ui_token_len = 0;
    unsigned int ui_blob_type = 0;
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 2)
    {
        goto unknow;
    }

    /* 取得token长度 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    ui_token_len = u16_token_len;
    /* 取得参数个数 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_params
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    ui_token_len -= 2;

    /* 解析类型 */
    while (ui_token_len)
    {
        /* NameLength + Status + UserType + DataType + LocaleLen */
        if (ui_token_len < 1 + 1 + 4 + 1 + 1)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        /* 跳过ParamName */
        bytebuff_get_char(p_st_data, &u8_name_len);
        if (ui_token_len < (unsigned int)(1 + u8_name_len + 1 + 4 + 1 + 1))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_name_len);
        ui_token_len -= 1 + u8_name_len;

        /* 取得status */
        bytebuff_get_char(p_st_data, &u8_status);
        /* The valid status bits and values are:0x01, 0x08 and 0x20 */
        //if (u8_status & 0xE6)
        //{
        //    frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
        //    return APM_L7_ANALYZE_FAIL;
        //}
        /* 跳过UserType */
        bytebuff_skip(p_st_data, 4);
        ui_token_len -= 5;

        /* 解析DataType */
        i_ret = __sybase_parse_data_type(p_st_data, p_st_session, &ui_token_len
                                        , &i_data_type, &ui_len, &ui_precision
                                        , &ui_scale, &ui_blob_type);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return i_ret;
        }

        /* 跳过local information */
        if (ui_token_len < 1)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_get_char(p_st_data, &u8_local_len);
        if (ui_token_len < (unsigned int)(1 + u8_local_len))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_local_len);
        ui_token_len -= 1 + u8_local_len;

        /* 创建节点 */
        p_st_metadata = (Sql_metadata_info *)frmalloc(sizeof(Sql_metadata_info));
        if (p_st_metadata == NULL)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_st_metadata, 0x0, sizeof(Sql_metadata_info));
        p_st_metadata->i_data_type = i_data_type;     /* 数据类型 */
        p_st_metadata->ui_len = ui_len;               /* 数据长度 */
        p_st_metadata->ui_precision = ui_precision;   /* precision */
        p_st_metadata->ui_scale = ui_scale;           /* scale */
        p_st_metadata->i_status = u8_status;          /* status */
        p_st_node = frlist_node_create(p_st_metadata);
        if (p_st_node == NULL)
        {
            frfree(p_st_metadata);
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        frlist_push(p_lst_metadata, p_st_node);
        u16_params--;
    }

    /* 判断解析了的参数个数 */
    if (u16_params != 0)
    {
        frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_PARAMFMT2 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_lst_metadata(metadata list)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data和p_lst_metadata必须不为NULL
*******************************************************************************/
int sybase_parse_paramfmt2_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , L7session_sybase *p_st_session
                                , Frlist_header *p_lst_metadata)
{
    /* 定义
    * 解析FRTDS_PARAMFMT2 = 0x20
    *                     Length(4byte unsigned integer)
    *                     #Params(2byte unsigned integer)
    *                     NameLength(1byte unsigned integer)
    *                     ParamName
    *                     Status(4byte unsigned integer)
    *                     UserType(4byte unsigned integer)
    *                     DataType(1byte unsigned integer)
    *                     Length(1byte unsigned integer)
    *                     Precision(1byte unsigned integer)
    *                     Scale(1byte unsigned integer)
    *                     LocalLen(1byte unsigned integer)
    *                     LocalInfo
    *                     ClassLen(2byte unsigned integer)
    *                     ClassID(1byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint32_t u32_status = 0;
    uint8_t u8_name_len = 0;
    uint16_t u16_params = 0;
    uint32_t u32_token_len = 0;
    uint8_t u8_local_len = 0;
    int i_data_type = 0;
    unsigned int ui_len = 0;
    unsigned int ui_scale = 0;
    unsigned int ui_precision = 0;
    unsigned int ui_token_len = 0;
    unsigned int ui_blob_type = 0;
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 4 + 2)
    {
        goto unknow;
    }

    /* 取得token长度 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_token_len
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (u32_token_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto unknow;
    }

    ui_token_len = u32_token_len;
    /* 取得参数个数 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_params
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    ui_token_len -= 2;

    /* 解析类型 */
    while (ui_token_len)
    {
        /* NameLength + Status + UserType + DataType + LocaleLen */
        if (ui_token_len < 1 + 4 + 4 + 1 + 1)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        /* 跳过ParamName */
        bytebuff_get_char(p_st_data, &u8_name_len);
        if (ui_token_len < (unsigned int)(1 + u8_name_len + 4 + 4 + 1 + 1))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_name_len);
        ui_token_len -= 1 + u8_name_len;

        /* 取得status */
        i_ret = bytebuff_get_int(p_st_data, 4, &u32_status
                                , p_st_session->i_lint4_endian);
        /* The valid status bits and values are:0x01, 0x08 and 0x20 */
        if (i_ret != FR_SUCC || u32_status & 0xE6)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        /* 跳过UserType */
        bytebuff_skip(p_st_data, 4);
        ui_token_len -= 8;

        /* 解析DataType */
        i_ret = __sybase_parse_data_type(p_st_data, p_st_session, &ui_token_len
                                        , &i_data_type, &ui_len, &ui_precision
                                        , &ui_scale, &ui_blob_type);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return i_ret;
        }

        /* 跳过local information */
        if (ui_token_len < 1)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_get_char(p_st_data, &u8_local_len);
        if (ui_token_len < (unsigned int)(1 + u8_local_len))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_local_len);
        ui_token_len -= 1 + u8_local_len;

        /* 创建节点 */
        p_st_metadata = (Sql_metadata_info *)frmalloc(sizeof(Sql_metadata_info));
        if (p_st_metadata == NULL)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_st_metadata, 0x0, sizeof(Sql_metadata_info));
        p_st_metadata->i_data_type = i_data_type;     /* 数据类型 */
        p_st_metadata->ui_len = ui_len;               /* 数据长度 */
        p_st_metadata->ui_precision = ui_precision;   /* precision */
        p_st_metadata->ui_scale = ui_scale;           /* scale */
        p_st_metadata->i_status = u32_status;          /* status */
        p_st_node = frlist_node_create(p_st_metadata);
        if (p_st_node == NULL)
        {
            frfree(p_st_metadata);
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        frlist_push(p_lst_metadata, p_st_node);
        u16_params--;
    }

    /* 判断解析了的参数个数 */
    if (u16_params != 0)
    {
        frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_PARAMS TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_lst_metadata(metadata)
*           :  i_get_value(是否需要取值)
*           :  p_st_bind_hd(参数信息)
*           :  (是否需要取值)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data肯定不能为NULL
*******************************************************************************/
int sybase_parse_params_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , L7session_sybase *p_st_session
                              , Frlist_header *p_lst_metadata
                              , int i_get_value
                              , Sql_field_bind **pp_lst_bind_hd)
{
    /* 定义
    * 解析FRTDS_PARAMS = 0xD7
    *                  Columnstatus(1byte unsigned integer)
    *                  Length(0, 1, or 4 bytes)
    *                  Paramter
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    Frlist_node *p_st_node = NULL;
    Frdata_field *p_st_value = NULL;
    Frlist_node *p_st_node_value = NULL;
    Sql_metadata_info *p_st_metadata = NULL;
    Sql_field_bind *p_lst_bind = NULL;

    /* 根据id取得对应的ALTFMT */
    p_st_node = FRLIST_FIRST_NODE(p_lst_metadata);
    /* 需要取得parameter值 */
    if (i_get_value)
    {
        /* 创建bind list */
        p_lst_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
        if (p_lst_bind == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_lst_bind, 0x0, sizeof(Sql_field_bind));
        /* 解析 */
        while (p_st_node)
        {
            p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
            /*
            *  Columnstatus only when the following two conditions have been met:
            *  The first is that the client and server have negotiated through the
            *  FRTDS_DATA_COLUMNSTATUS and FRTDS_DATA_NOCOLUMNSTATUS capability bits
            *  that the client can send columnstatus bytes to the server.
            *  And secondly, the PARAMFMT token for this parameter has the
            *  FRTDS_PARAM_COLUMNSTATUS status bit set.
            */
            if (p_st_session->i_columnstatus == FR_YES
                && p_st_session->i_nocolumnstatus == FR_NO
                && p_st_metadata->i_status & 0x80)
            {
                if (bytebuff_remaining(p_st_data) < 1)
                {
                    goto unknow;
                }
                /* get Columnstatus */
                bytebuff_get_char(p_st_data, &u8_status);
            }

            if (u8_status == 0x00 || u8_status == 0x02)
            {
                /* 解析data */
                i_ret = __sybase_get_data(p_st_data , i_whole_flg , p_st_session
                                         , p_st_metadata, &p_st_value);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("Call __sybase_get_data failed\n");
                    frdb_field_bind_free(&p_lst_bind);
                    return i_ret;
                }
                p_st_node_value = frlist_node_create(p_st_value);
                if (p_st_node_value == NULL)
                {
                    frdbg("Create node failed\n");
                    frdb_field_bind_free(&p_lst_bind);
                    frtds_free_param(&p_st_value);
                    return APM_L7_ANALYZE_FAIL;
                }
                frlist_push(&p_lst_bind->st_field_list, p_st_node_value);
            }
            /* 0x01 means No Data follows, the value is NULL, else Not valid */
            else if (u8_status != 0x01)
            {
                frdbg("Status is incorrect\n");
                frdb_field_bind_free(&p_lst_bind);
                return APM_L7_ANALYZE_FAIL;
            }
            /* 取得下一个DataType */
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
        }

        *pp_lst_bind_hd = p_lst_bind;
    }
    else /* 不需要取得parameter值 */
    {
        while (p_st_node)
        {
            p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
            /*
            *  Columnstatus only when the following two conditions have been met:
            *  The first is that the client and server have negotiated through the
            *  FRTDS_DATA_COLUMNSTATUS and FRTDS_DATA_NOCOLUMNSTATUS capability bits
            *  that the client can send columnstatus bytes to the server.
            *  And secondly, the PARAMFMT token for this parameter has the
            *  FRTDS_PARAM_COLUMNSTATUS status bit set.
            */
            if (p_st_session->i_columnstatus == FR_YES
                && p_st_session->i_nocolumnstatus == FR_NO
                && p_st_metadata->i_status & 0x80)
            {
                if (bytebuff_remaining(p_st_data) < 1)
                {
                    goto unknow;
                }
                /* get Columnstatus */
                bytebuff_get_char(p_st_data, &u8_status);
            }

            if (u8_status == 0x00 || u8_status == 0x02)
            {
                i_ret = __sybase_skip_data(p_st_data, i_whole_flg
                                          , p_st_session, p_st_metadata);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("Call __sybase_skip_data failed\n");
                    return i_ret;
                }
            }
            /* 0x01 means No Data follows, the value is NULL, else Not valid */
            else if (u8_status != 0x01)
            {
                frdbg("Status is incorrect\n");
                return APM_L7_ANALYZE_FAIL;
            }
            /* 取得下一个DataType */
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
        }
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_RPC TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int sybase_parse_rpc_token(Frbyte_Packet *p_st_data
                           , int i_whole_flg
                           , L7session_sybase *p_st_session
                           , char **pp_rpc_name
                           , Sql_field_bind **pp_lst_bind_hd)
{
    /* 定义
    * 解析FRTDS_RPC = 0xE0
    *               Length(2byte signed integer)
    *               NameLen(1byte signed integer)
    *               RPCName
    *               Options(2byte signed integer)
    *               NameLen(1byte signed integer)
    *               ParamName
    *               Status(1byte signed integer)
    *               DataType(1byte signed integer)
    *               MaxLen(0, 1, 2, or 4 bytes)
    *               Precision(1byte signed integer)
    *               Scale(1byte signed integer)
    *               ActualLen(0, 1, 2, or 4 bytes)
    *               ParamData
    */

    int i_ret = FR_SUCC;
    uint8_t u8_name_len = 0;
    uint16_t u16_options = 0;
    uint16_t u16_token_len = 0;
    int i_data_type = 0;
    unsigned int ui_len = 0;
    unsigned int ui_scale = 0;
    unsigned int ui_precision = 0;
    unsigned int ui_token_len = 0;
    unsigned int ui_blob_type = 0;
    unsigned int ui_org_len = 0;
    unsigned int ui_end_len = 0;
    char *p_rpc_name = NULL;
    Frlist_node *p_st_node_value = NULL;
    Frdata_field *p_st_value = NULL;
    Sql_field_bind *p_lst_bind = NULL;
    Sql_metadata_info st_metadata;

    /* 基本格式检查(Length + NameLen + Options) */
    if (bytebuff_remaining(p_st_data) < 2 + 1 + 2)
    {
        goto unknow;
    }
    /* 取得Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }
    /* 取得rpc name */
    i_ret = bytebuff_get_char(p_st_data, &u8_name_len);
    if (u16_token_len < 1 + u8_name_len + 2)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_rpc_name = (char *)frmalloc(u8_name_len + 1);
    if (p_rpc_name == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_rpc_name, u8_name_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_rpc_name);
        return APM_L7_ANALYZE_FAIL;
    }
    p_rpc_name[u8_name_len] = '\0';

    /* 取得OPTIONS */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_options
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC || u16_options & 0xFFFE)
    {
        frfree(p_rpc_name);
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= 1 + u8_name_len + 2;
    ui_token_len = u16_token_len;
    if (ui_token_len)
    {
        /* 创建bind list */
        p_lst_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
        if (p_lst_bind == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_lst_bind, 0x0, sizeof(Sql_field_bind));
    }

    /* 解析参数 */
    while (ui_token_len)
    {
        /* 解析DataType */
        i_ret = __sybase_parse_data_type(p_st_data, p_st_session, &ui_token_len
                                        , &i_data_type, &ui_len, &ui_precision
                                        , &ui_scale, &ui_blob_type);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frfree(p_rpc_name);
            frdb_field_bind_free(&p_lst_bind);
            return i_ret;
        }
        st_metadata.i_data_type = i_data_type;     /* 数据类型 */
        st_metadata.ui_len = ui_len;               /* 数据长度 */
        st_metadata.ui_precision = ui_precision;   /* precision */
        st_metadata.ui_scale = ui_scale;           /* scale */
        st_metadata.i_status = 0;                  /* status */

        /* 解析data */
        ui_org_len = bytebuff_remaining(p_st_data);
        i_ret = __sybase_get_data(p_st_data , i_whole_flg , p_st_session
                                 , &st_metadata, &p_st_value);
        ui_end_len = bytebuff_remaining(p_st_data);
        if (ui_token_len < ui_org_len - ui_end_len)
        {
            frfree(p_rpc_name);
            frdb_field_bind_free(&p_lst_bind);
            frtds_free_param(&p_st_value);
            return APM_L7_ANALYZE_FAIL;
        }
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frfree(p_rpc_name);
            frdb_field_bind_free(&p_lst_bind);
            return i_ret;
        }

        ui_token_len -= ui_org_len - ui_end_len;
        p_st_node_value = frlist_node_create(p_st_value);
        if (p_st_node_value == NULL)
        {
            frdbg("Create node failed\n");
            frfree(p_rpc_name);
            frdb_field_bind_free(&p_lst_bind);
            frtds_free_param(&p_st_value);
            return APM_L7_ANALYZE_FAIL;
        }
        p_st_value = NULL;
        frlist_push(&p_lst_bind->st_field_list, p_st_node_value);
    }

    /* 设置出力 */
    *pp_lst_bind_hd = p_lst_bind;
    *pp_rpc_name = p_rpc_name;
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_RETURNSTATUS TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int sybase_parse_returnstatus_token(Frbyte_Packet *p_st_data
                                    , int i_whole_flg
                                    , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_RETURNSTATUS = 0x79
    *                        Value(2byte signed integer)
    */
    //int i_ret = FR_SUCC;
    //uint32_t u32_token_len = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 4)
    {
        if (i_whole_flg == FR_YES)
        {
            /* 格式不正 */
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            /* 数据不足 */
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* skip Value */
    bytebuff_skip(p_st_data, 4);

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_RETURNVALUE TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int sybase_parse_returnvalue_token(Frbyte_Packet *p_st_data
                                  , int i_whole_flg
                                  , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_RETURNVALUE = 0xAC
    *                       Length(2byte unsigned integer)
    *                       NameLen(1byte unsigned integer)
    *                       ParamName
    *                       Status(1byte unsigned integer)
    *                       UserType(4byte unsigned integer)
    *                       DataType(1byte unsigned integer)
    *                       MaxLen(1 0r 2 or 4 bytes)
    *                       Precision(1byte unsigned integer)
    *                       Scale(1byte unsigned integer)
    *                       ActualLen(1, 2, or 4 bytes)
    *                       Data
    */
    int i_ret = FR_SUCC;
    uint8_t u8_name_len = 0;
    uint8_t u8_status = 0;
    uint16_t u16_token_len = 0;
    int i_data_type = 0;
    unsigned int ui_len = 0;
    unsigned int ui_scale = 0;
    unsigned int ui_precision = 0;
    unsigned int ui_blob_type = 0;
    unsigned int ui_len_tmp = 0;
    unsigned int ui_token_len = 0;
    Sql_metadata_info st_metadata;
    memset(&st_metadata, 0x0, sizeof(Sql_metadata_info));

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2 + 1 + 1 + 4 + 1 + 1 + 1)
    {
        goto unknow;
    }

    /* 取得token长度 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* TODO 为了提高性能可以不做具体的内容check,直接skip */
    //bytebuff_skip(p_st_data, u16_token_len);
    //return APM_L7_ANALYZE_SUCC;

    ui_token_len = u16_token_len;
    /* 取得NameLen */
    bytebuff_get_char(p_st_data, &u8_name_len);
    if (ui_token_len < (unsigned int)(1 + u8_name_len + 1 + 4 + 1 + 1 + 1))
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* skip Param name */
    bytebuff_skip(p_st_data, u8_name_len);
    ui_token_len -= 1 + u8_name_len;

    /* 取得status */
    bytebuff_get_char(p_st_data, &u8_status);
    if (u8_status >= 3)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* skip user type */
    bytebuff_skip(p_st_data, 4);
    ui_token_len -= 1 + 4;
    /* 解析datatype */
    i_ret = __sybase_parse_data_type(p_st_data, p_st_session, &ui_token_len
                                    , &i_data_type, &ui_len, &ui_precision
                                    , &ui_scale, &ui_blob_type);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    st_metadata.i_data_type = i_data_type;     /* 数据类型 */
    st_metadata.ui_len = ui_len;               /* 数据长度 */
    st_metadata.ui_precision = ui_precision;   /* precision */
    st_metadata.ui_scale = ui_scale;           /* scale */
    st_metadata.i_status = u8_status;          /* status */

    ui_len_tmp = bytebuff_remaining(p_st_data);
    /* 跳过数据 */
    i_ret = __sybase_skip_data(p_st_data, i_whole_flg
                              , p_st_session, &st_metadata);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    ui_len_tmp -= bytebuff_remaining(p_st_data);
    if (ui_len_tmp != ui_token_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ROW TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int sybase_parse_row_token(Frbyte_Packet *p_st_data
                          , int i_whole_flg
                          , L7session_sybase *p_st_session
                          , Frlist_header *p_lst_metadata)
{
    /* 定义
    * 解析FRTDS_ROW = 0xD1
    *               Columnstatus(1byte unsigned integer)
    *               Length(0, 1, or 4 bytes)
    *               NameLength(1byte unsigned integer)
    *               Data
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    /* 根据id取得对应的ALTFMT */
    p_st_node = FRLIST_FIRST_NODE(p_lst_metadata);
    while (p_st_node)
    {
        p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
        /*
        *  Columnstatus only when the following two conditions have been met:
        *  The first is that the client and server have negotiated through the
        *  FRTDS_DATA_COLUMNSTATUS and FRTDS_DATA_NOCOLUMNSTATUS capability bits
        *  that the client can send columnstatus bytes to the server.
        *  And secondly, the PARAMFMT token for this parameter has the
        * FRTDS_PARAM_COLUMNSTATUS status bit set.
        */
        if (p_st_session->i_columnstatus == FR_YES
            && p_st_session->i_nocolumnstatus == FR_NO
            && p_st_metadata->i_status & 0x80)
        {
            if (bytebuff_remaining(p_st_data) < 1)
            {
                goto unknow;
            }
            /* get Columnstatus */
            bytebuff_get_char(p_st_data, &u8_status);
        }

        if (u8_status == 0x00 || u8_status == 0x02)
        {
            /* 解析data */
            i_ret = __sybase_skip_data(p_st_data, i_whole_flg
                                      , p_st_session, p_st_metadata);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                return i_ret;
            }
        }
        /* 0x01 means No Data follows, the value is NULL, else Not valid */
        else if (u8_status != 0x01)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得下一个DataType */
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ROWFMT TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_lst_metadata(metadata list)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data和p_lst_metadata必须不为NULL
*******************************************************************************/
int sybase_parse_rowfmt_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , L7session_sybase *p_st_session
                                , Frlist_header *p_lst_metadata)
{
    /* 定义
    * 解析FRTDS_ROWFMT = 0xEE
    *                  Length(2byte unsigned integer)
    *                  #Cols(2byte unsigned integer)
    *                  NameLength(1byte unsigned integer)
    *                  ColumnName
    *                  Status(1byte unsigned integer)
    *                  UserType(4byte unsigned integer)
    *                  DataType(1byte unsigned integer)
    *                  Length(1byte unsigned integer)
    *                  Precision(1byte unsigned integer)
    *                  Scale(1byte unsigned integer)
    *                  LocalLen(1byte unsigned integer)
    *                  LocalInfo
    *                  ClassLen(2byte unsigned integer)
    *                  ClassID(1byte unsigned integer)
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    i_ret = sybase_parse_paramfmt_token(p_st_data, i_whole_flg
                                       , p_st_session, p_lst_metadata);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_ROWFMT2 TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*           :  p_lst_metadata(metadata list)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data和p_lst_metadata必须不为NULL
*******************************************************************************/
int sybase_parse_rowfmt2_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , L7session_sybase *p_st_session
                               , Frlist_header *p_lst_metadata)
{
    /* 定义
    * 解析FRTDS_ROWFMT2 = 0x61
    *                   Length(4byte unsigned integer)
    *                   #Cols(2byte unsigned integer)
    *                   LabelLen(1byte unsigned integer)
    *                   ColumnLabel
    *                   CatalogLen(1byte unsigned integer)
    *                   CatalogName
    *                   SchemaLen(1byte unsigned integer)
    *                   SchamaName
    *                   TableLen(1byte unsigned integer)
    *                   TableName
    *                   ColumnLen(1byte unsigned integer)
    *                   ColumnName
    *                   Status(4byte unsigned integer)
    *                   UserType(4byte unsigned integer)
    *                   DataType(1byte unsigned integer)
    *                   Length(1byte unsigned integer)
    *                   Precision(1byte unsigned integer)
    *                   Scale(1byte unsigned integer)
    *                   LocaleLen(1byte unsigned integer)
    *                   LocaleInfo
    *                   ClassLen(2byte unsigned integer)
    *                   ClassID(1byte unsigned integer)
    */
    int i_ret = FR_SUCC;
    uint16_t u16_cols = 0;
    uint8_t u8_label_len = 0;
    uint8_t u8_catalog_len = 0;
    uint8_t u8_schema_len = 0;
    uint8_t u8_table_len = 0;
    uint8_t u8_column_len = 0;
    uint32_t u32_token_len = 0;
    uint32_t u32_status = 0;
    uint8_t u8_local_len = 0;
    int i_data_type = 0;
    unsigned int ui_len = 0;
    unsigned int ui_scale = 0;
    unsigned int ui_precision = 0;
    unsigned int ui_token_len = 0;
    unsigned int ui_blob_type = 0;
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 4 + 2)
    {
        goto unknow;
    }

    /* 取得token长度 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_token_len
                            , p_st_session->i_lint4_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (u32_token_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto unknow;
    }

    ui_token_len = u32_token_len;
    /* 取得列数 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_cols
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    ui_token_len -= 2;

    /* 解析类型 */
    while (ui_token_len)
    {
        /*
        *  LabelLen + CatalogLen + SchemaLen + TableLen + ColumnLen
        *  + Status + UserType + DataType + LocaleLen
        */
        if (ui_token_len < 1 + 1 + 1 + 1 + 1 + 4 + 4 + 1 + 1)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }

        /* 跳过ColumnLabel */
        bytebuff_get_char(p_st_data, &u8_label_len);
        if (ui_token_len < (unsigned int)(1 + u8_label_len + 1 + 1 + 1 + 1 + 4 + 4 + 1 + 1))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_label_len);
        ui_token_len -= 1 + u8_label_len;

        /* 跳过CatalogName */
        bytebuff_get_char(p_st_data, &u8_catalog_len);
        if (ui_token_len < (unsigned int)(1 + u8_catalog_len + 1 + 1 + 1 + 4 + 4 + 1 + 1))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_catalog_len);
        ui_token_len -= 1 + u8_catalog_len;

        /* 跳过SchamaName */
        bytebuff_get_char(p_st_data, &u8_schema_len);
        if (ui_token_len < (unsigned int)(1 + u8_schema_len + 1 + 1 + 4 + 4 + 1 + 1))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_schema_len);
        ui_token_len -= 1 + u8_schema_len;

        /* 跳过TableName */
        bytebuff_get_char(p_st_data, &u8_table_len);
        if (ui_token_len < (unsigned int)(1 + u8_table_len + 1 + 4 + 4 + 1 + 1))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_table_len);
        ui_token_len -= 1 + u8_table_len;

        /* 跳过ColumnName */
        bytebuff_get_char(p_st_data, &u8_column_len);
        if (ui_token_len < (unsigned int)(1 + u8_column_len + 4 + 4 + 1 + 1))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_column_len);
        ui_token_len -= 1 + u8_column_len;

        /* 取得status */
        i_ret = bytebuff_get_int(p_st_data, 4, &u32_status
                                , p_st_session->i_lint4_endian);
        if (i_ret != FR_SUCC)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        /* 跳过UserType */
        bytebuff_skip(p_st_data, 4);
        ui_token_len -= 8;

        /* 解析DataType */
        i_ret = __sybase_parse_data_type(p_st_data, p_st_session, &ui_token_len
                                        , &i_data_type, &ui_len, &ui_precision
                                        , &ui_scale, &ui_blob_type);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return i_ret;
        }

        /* 跳过local information */
        if (ui_token_len < 1)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_get_char(p_st_data, &u8_local_len);
        if (ui_token_len < (unsigned int)(1 + u8_local_len))
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_local_len);
        ui_token_len -= 1 + u8_local_len;

        /* 创建节点 */
        p_st_metadata = (Sql_metadata_info *)frmalloc(sizeof(Sql_metadata_info));
        if (p_st_metadata == NULL)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        memset(p_st_metadata, 0x0, sizeof(Sql_metadata_info));
        p_st_metadata->i_data_type = i_data_type;     /* 数据类型 */
        p_st_metadata->ui_len = ui_len;               /* 数据长度 */
        p_st_metadata->ui_precision = ui_precision;   /* precision */
        p_st_metadata->ui_scale = ui_scale;           /* scale */
        p_st_metadata->i_status = u32_status;         /* status */
        p_st_node = frlist_node_create(p_st_metadata);
        if (p_st_node == NULL)
        {
            frfree(p_st_metadata);
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        frlist_push(p_lst_metadata, p_st_node);
        u16_cols--;
    }

    /* 判断解析了的参数个数 */
    if (u16_cols != 0)
    {
        frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析FRTDS_TABNAME TOKEN
*  ARGS     :  p_st_data(bytebuff数据)
*           :  i_whole_flg(packet是否完整标识)
*           :  p_st_session(sybase session信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (need more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int sybase_parse_tabname_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , L7session_sybase *p_st_session)
{
    /* 定义
    * 解析FRTDS_TABNAME = 0xA4
    *                   Length(2byte unsigned integer)
    *                   NameLength(1byte unsigned integer)
    *                   TableName
    */
    int i_ret = FR_SUCC;
    uint8_t u8_name_len = 0;
    uint16_t u16_token_len = 0;

    /* 基本格式检查 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        goto unknow;
    }

    /* 取得FRTDS_COLINFO的总长度Length */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_token_len
                              , p_st_session->i_lint2_endian);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 长度check */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto unknow;
    }

    /* TODO 为了提高性能可以不做具体的内容check,直接skip */
    //bytebuff_skip(p_st_data, u16_token_len);
    //return APM_L7_ANALYZE_SUCC;

    while (u16_token_len)
    {
        /* skip column name */
        bytebuff_get_char(p_st_data, &u8_name_len);
        if (u16_token_len < 1 + u8_name_len)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        bytebuff_skip(p_st_data, u8_name_len);
        u16_token_len -= 1 + u8_name_len;
    }

    return APM_L7_ANALYZE_SUCC;

unknow:
    if (i_whole_flg == FR_YES)
    {
        /* 格式不正 */
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        /* 数据不足 */
        return APM_L7_ANALYZE_TODO;
    }
}
